@khanacademy/perseus-editor 38.1.3 → 40.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/all-editors.d.ts +49 -9
  2. package/dist/article-editor.d.ts +2 -1
  3. package/dist/components/util.d.ts +0 -1
  4. package/dist/components/widget-editor.d.ts +1 -1
  5. package/dist/es/index.js +135 -140
  6. package/dist/es/index.js.map +1 -1
  7. package/dist/{item-extras-editor.d.ts → extras-editor.d.ts} +2 -2
  8. package/dist/index.js +134 -139
  9. package/dist/index.js.map +1 -1
  10. package/dist/item-editor.d.ts +3 -3
  11. package/dist/styles/global-colors.d.ts +0 -5
  12. package/dist/testing/feature-flags-util.d.ts +2 -0
  13. package/dist/widgets/categorizer-editor/categorizer-editor.d.ts +0 -1
  14. package/dist/widgets/cs-program-editor/cs-program-editor.d.ts +0 -1
  15. package/dist/widgets/definition-editor/definition-editor.d.ts +0 -1
  16. package/dist/widgets/deprecated-standin-editor/deprecated-standin-editor.d.ts +0 -1
  17. package/dist/widgets/dropdown-editor/dropdown-editor.d.ts +0 -1
  18. package/dist/widgets/explanation-editor/explanation-editor.d.ts +0 -1
  19. package/dist/widgets/expression-editor/expression-editor.d.ts +0 -1
  20. package/dist/widgets/free-response-editor/free-response-editor.d.ts +0 -1
  21. package/dist/widgets/graded-group-editor/graded-group-editor.d.ts +0 -1
  22. package/dist/widgets/graded-group-set-editor/graded-group-set-editor.d.ts +0 -1
  23. package/dist/widgets/grapher-editor/grapher-editor.d.ts +0 -1
  24. package/dist/widgets/group-editor/group-editor.d.ts +0 -1
  25. package/dist/widgets/iframe-editor/iframe-editor.d.ts +0 -1
  26. package/dist/widgets/image-editor/image-editor.d.ts +0 -1
  27. package/dist/widgets/input-number-editor/input-number-editor.d.ts +0 -1
  28. package/dist/widgets/interaction-editor/interaction-editor.d.ts +0 -1
  29. package/dist/widgets/interactive-graph-editor/interactive-graph-editor.d.ts +62 -29
  30. package/dist/widgets/label-image-editor/label-image-editor.d.ts +0 -1
  31. package/dist/widgets/label-image-editor/marker.d.ts +5 -19
  32. package/dist/widgets/matcher-editor/matcher-editor.d.ts +0 -1
  33. package/dist/widgets/matrix-editor/matrix-editor.d.ts +0 -1
  34. package/dist/widgets/measurer-editor/measurer-editor.d.ts +0 -1
  35. package/dist/widgets/number-line-editor/number-line-editor.d.ts +0 -1
  36. package/dist/widgets/numeric-input-editor/numeric-input-editor.d.ts +0 -1
  37. package/dist/widgets/orderer-editor/orderer-editor.d.ts +0 -1
  38. package/dist/widgets/phet-simulation-editor/phet-simulation-editor.d.ts +0 -1
  39. package/dist/widgets/plotter-editor/plotter-editor.d.ts +0 -1
  40. package/dist/widgets/python-program-editor/python-program-editor.d.ts +0 -1
  41. package/dist/widgets/radio-editor/radio-editor.d.ts +0 -1
  42. package/dist/widgets/sorter-editor/sorter-editor.d.ts +0 -1
  43. package/dist/widgets/table-editor/table-editor.d.ts +0 -1
  44. package/dist/widgets/video-editor/video-editor.d.ts +0 -1
  45. package/package.json +13 -11
  46. package/dist/components/dropdown-option.d.ts +0 -31
package/dist/es/index.js CHANGED
@@ -27,7 +27,7 @@ import IconButton from '@khanacademy/wonder-blocks-icon-button';
27
27
  import Link from '@khanacademy/wonder-blocks-link';
28
28
  import Tooltip from '@khanacademy/wonder-blocks-tooltip';
29
29
  import questionIcon from '@phosphor-icons/core/regular/question.svg';
30
- import { SingleSelect, OptionItem, ActionMenu, ActionItem } from '@khanacademy/wonder-blocks-dropdown';
30
+ import { SingleSelect, OptionItem, ActionMenu, ActionItem, Listbox } from '@khanacademy/wonder-blocks-dropdown';
31
31
  import { UnreachableCaseError, isTruthy } from '@khanacademy/wonder-stuff-core';
32
32
  import katex from 'katex';
33
33
  import classNames from 'classnames';
@@ -61,12 +61,13 @@ import arrowFatLeft from '@phosphor-icons/core/regular/arrow-fat-left.svg';
61
61
  import arrowFatRight from '@phosphor-icons/core/regular/arrow-fat-right.svg';
62
62
  import arrowFatUp from '@phosphor-icons/core/regular/arrow-fat-up.svg';
63
63
  import minusCircle from '@phosphor-icons/core/regular/minus-circle.svg';
64
+ import { Popover, PopoverContentCore } from '@khanacademy/wonder-blocks-popover';
64
65
  import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
65
66
  import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
66
67
  import arrowDown from '@phosphor-icons/core/regular/arrow-down.svg';
67
68
  import arrowUp from '@phosphor-icons/core/regular/arrow-up.svg';
68
69
 
69
- const libName="@khanacademy/perseus-editor";const libVersion="38.1.3";addLibraryVersionToPerseusDebug(libName,libVersion);
70
+ const libName="@khanacademy/perseus-editor";const libVersion="40.0.0";addLibraryVersionToPerseusDebug(libName,libVersion);
70
71
 
71
72
  var jsxRuntime = {exports: {}};
72
73
 
@@ -1422,35 +1423,35 @@ const IMAGE_MARKDOWN_REGEX=/!\[[^\]]*\]\([^)]+\)/g;function getFirstAvailableWid
1422
1423
 
1423
1424
  const defaultItemEditorContext={question:{content:"",widgets:{},images:{}},onEditorChange:()=>{}};const ItemEditorContext=React.createContext(defaultItemEditorContext);function useItemEditorContext(){return React.useContext(ItemEditorContext)}
1424
1425
 
1425
- const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext();const cta=getCtaForIssueId(issue.id,question,onEditorChange);if(!cta){return null}return jsxRuntimeExports.jsx(Button,{size:"small",onClick:cta.onClick,style:styles$Y.button,children:cta.label},issue.id)};const styles$Y={button:{marginTop:sizing.size_080,marginBottom:sizing.size_080}};
1426
+ const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext();const cta=getCtaForIssueId(issue.id,question,onEditorChange);if(!cta){return null}return jsxRuntimeExports.jsx(Button,{size:"small",onClick:cta.onClick,style:styles$X.button,children:cta.label},issue.id)};const styles$X={button:{marginTop:sizing.size_080,marginBottom:sizing.size_080}};
1426
1427
 
1427
- const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$X.container,containerStyle],headerStyle:[styles$X.accordionHeader,headerStyle],header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$X.accordionPanel,panelStyle],children:children})})})};const styles$X=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.instructive.subtle,marginBlockStart:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingBlockStart:spacing.xxSmall_6,paddingBlockEnd:spacing.xxxSmall_4,paddingInlineStart:spacing.small_12,paddingInlineEnd:spacing.small_12}});
1428
+ const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$W.container,containerStyle],headerStyle:[styles$W.accordionHeader,headerStyle],header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$W.accordionPanel,panelStyle],children:children})})})};const styles$W=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.instructive.subtle,marginBlockStart:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingBlockStart:spacing.xxSmall_6,paddingBlockEnd:spacing.xxxSmall_4,paddingInlineStart:spacing.small_12,paddingInlineEnd:spacing.small_12}});
1428
1429
 
1429
1430
  const showMeStyle={marginBlockStart:"1em",display:"flex",alignItems:"center"};const ShowMe=({instanceId})=>{const[showMe,setShowMe]=React.useState(false);const context=React.useContext(A11yContext);React.useEffect(()=>{return ()=>{if(instanceId!=null){context?.setIssueHighlight(instanceId,false);}}},[]);if(instanceId==null||context==null){return jsxRuntimeExports.jsx("div",{children:"Unable to find the offending element. Please ask a developer for help fixing this."})}const handleChange=checked=>{setShowMe(checked);context.setIssueHighlight(instanceId,checked);};return jsxRuntimeExports.jsxs(BodyText,{size:"small",tag:"span",weight:"bold",style:showMeStyle,children:[jsxRuntimeExports.jsx("span",{style:{marginInlineEnd:"1em"},children:"Show Me"}),jsxRuntimeExports.jsx(Switch,{checked:showMe,onChange:handleChange,"aria-label":"Show Me"})]})};
1430
1431
 
1431
1432
  const impactStringMap={high:"Error",medium:"Warning",low:"Guideline"};const IssueDetails=({issue})=>{const[expanded,setExpanded]=React.useState(false);const toggleVisibility=()=>setExpanded(!expanded);const accordionColor=issue.impact==="high"?semanticColor.feedback.critical.subtle.background:semanticColor.feedback.warning.subtle.background;const messageStyling={whiteSpace:"pre-line",color:semanticColor.core.foreground.critical.default};return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:accordionColor},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",style:{textOverflow:"ellipsis",maxInlineSize:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`${impactStringMap[issue.impact]}: ${issue.id}`}),children:[jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",style:{marginBlockStart:"1em"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",weight:"bold",style:{marginBlockStart:"1em"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{style:messageStyling,children:issue.message}),jsxRuntimeExports.jsx(ShowMe,{instanceId:issue.source==="a11y"?issue.instanceId:undefined}),jsxRuntimeExports.jsx(IssueCta,{issue:issue})]})};
1432
1433
 
1433
- const LabeledSwitch=props=>{const{checked,label,labelSide="end",size="medium",style,disabled=false,onChange}=props;const switchId=useId();const labelElement=jsxRuntimeExports.jsx(BodyText,{size:size==="small"?"small":undefined,tag:"label",htmlFor:switchId,children:label});const strut=jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8});return jsxRuntimeExports.jsxs(View,{style:[styles$W.row,style],children:[labelSide==="start"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[labelElement,strut]}),jsxRuntimeExports.jsx(Switch,{id:switchId,checked:checked,disabled:disabled,onChange:onChange}),labelSide==="end"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[strut,labelElement]})]})};const styles$W=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"}});
1434
+ const LabeledSwitch=props=>{const{checked,label,labelSide="end",size="medium",style,disabled=false,onChange}=props;const switchId=useId();const labelElement=jsxRuntimeExports.jsx(BodyText,{size:size==="small"?"small":undefined,tag:"label",htmlFor:switchId,children:label});const strut=jsxRuntimeExports.jsx(Strut,{size:spacing.xSmall_8});return jsxRuntimeExports.jsxs(View,{style:[styles$V.row,style],children:[labelSide==="start"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[labelElement,strut]}),jsxRuntimeExports.jsx(Switch,{id:switchId,checked:checked,disabled:disabled,onChange:onChange}),labelSide==="end"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[strut,labelElement]})]})};const styles$V=StyleSheet.create({row:{flexDirection:"row",alignItems:"center"}});
1434
1435
 
1435
- function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$V.expanded:styles$V.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$V=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
1436
+ function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$U.expanded:styles$U.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$U=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
1436
1437
 
1437
1438
  function getIssueKey(issue){return issue.instanceId??issue.id}const IssuesPanel=props=>{const{issues=[]}=props;const context=useContext(A11yContext);const[showPanel,setShowPanel]=useState(false);const axeCoreIssues=context?.a11yScanningEnabled?context.axeCoreIssues:[];const allIssues=[...issues,...axeCoreIssues];const hasWarnings=allIssues.length>0;const hasErrors=allIssues.some(issue=>issue.impact==="high");const issuesCount=`${allIssues.length} issue${allIssues.length===1?"":"s"}`;const icon=hasErrors?iconAlert:hasWarnings?iconWarning:iconPass;const iconColor=hasErrors?semanticColor.feedback.critical.strong.icon:hasWarnings?semanticColor.feedback.warning.strong.icon:semanticColor.feedback.success.strong.icon;const impactOrder={high:3,medium:2,low:1};const sortedIssues=[...allIssues].sort((a,b)=>{if(impactOrder[b.impact]!==impactOrder[a.impact]){return impactOrder[b.impact]-impactOrder[a.impact]}return a.id.localeCompare(b.id)});return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:()=>setShowPanel(!showPanel),children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginInlineEnd:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-content",children:[sortedIssues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{issue:issue},getIssueKey(issue))),allIssues.length===0&&jsxRuntimeExports.jsx("div",{children:"No issues found"}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Include axe-core scan",checked:context?.a11yScanningEnabled??false,onChange:enabled=>{context?.setA11yScanningEnabled(enabled);},style:{marginBlockStart:"1rem"}})]})})]})};
1438
1439
 
1439
1440
  class JsonEditor extends React.Component{getInitialState(){return {currentValue:JSON.stringify(this.props.value,null,4),valid:true}}componentDidUpdate(prevProps){if(!_.isEqual(prevProps.value,this.props.value)){const shouldReplaceContent=!this.state.valid||!_.isEqual(this.props.value,this.getCurrentValueAsJson());if(shouldReplaceContent){this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}}getCurrentValueAsJson(){try{return this.state.currentValue?this.typesafeParseOrThrow(this.state.currentValue):{}}catch{return null}}handleKeyDown(e){if(e.key==="Tab"){const textarea=e.currentTarget;const cursorPos=textarea.selectionStart;const v=textarea.value;const textBefore=v.substring(0,cursorPos);const textAfter=v.substring(cursorPos,v.length);textarea.value=textBefore+" "+textAfter;textarea.selectionStart=textBefore.length+4;textarea.selectionEnd=textBefore.length+4;e.preventDefault();this.processChange(textarea.value);}}handleChange(e){this.processChange(e.target.value);}processChange(nextString){try{const json=this.typesafeParseOrThrow(nextString);this.setState({currentValue:nextString,valid:true},()=>{this.props.onChange(json);});}catch{this.setState({currentValue:nextString,valid:false});}}handleBlur(e){const nextString=e.target.value;try{const json=this.typesafeParseOrThrow(nextString);this.setState({currentValue:JSON.stringify(json,null,4),valid:true},()=>{this.props.onChange(json);});}catch{this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}typesafeParseOrThrow(json){const parsed=this.props.parser(json);if(isSuccess(parsed)){return parsed.value}const parsedFromQuotedString=this.props.parser(JSON.parse(json));if(isSuccess(parsedFromQuotedString)){return parsedFromQuotedString.value}throw new TypeError("JsonEditor: parse failure")}render(){const classes="perseus-json-editor "+(this.state.valid?"valid":"invalid");return jsxRuntimeExports.jsx("textarea",{className:classes,value:this.state.currentValue,onChange:this.handleChange,onKeyDown:this.handleKeyDown,onBlur:this.handleBlur,disabled:this.props.editingDisabled})}constructor(props){super(props);this.state=this.getInitialState();this.handleBlur=this.handleBlur.bind(this);this.handleChange=this.handleChange.bind(this);this.handleKeyDown=this.handleKeyDown.bind(this);}}
1440
1441
 
1441
- const SectionControlButton=({icon,onClick,title,disabled})=>{return jsxRuntimeExports.jsx(IconButton,{icon:icon,disabled:disabled,"aria-label":title,style:styles$U.button,size:"xsmall",onClick:onClick})};const styles$U=StyleSheet.create({button:{marginInlineStart:5}});
1442
+ const SectionControlButton=({icon,onClick,title,disabled})=>{return jsxRuntimeExports.jsx(IconButton,{icon:icon,disabled:disabled,"aria-label":title,style:styles$T.button,size:"xsmall",onClick:onClick})};const styles$T=StyleSheet.create({button:{marginInlineStart:5}});
1442
1443
 
1443
1444
  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{shouldDragHighlight,...forwardProps}=this.props;return jsxRuntimeExports.jsx(View,{...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={shouldDragHighlight:()=>true};
1444
1445
 
1445
- const InfoTipBase=props=>{return jsxRuntimeExports.jsx(Tooltip,{content:jsxRuntimeExports.jsx(BodyText,{style:styles$T.body,children:props.children}),placement:"right",children:jsxRuntimeExports.jsx(PhosphorIcon,{size:"small",icon:questionIcon,style:styles$T.spacingLeft})})};const styles$T=StyleSheet.create({spacingLeft:{marginInlineStart:spacing.xxxSmall_4},body:{padding:spacing.medium_16}});
1446
+ const InfoTipBase=props=>{return jsxRuntimeExports.jsx(Tooltip,{content:jsxRuntimeExports.jsx(BodyText,{style:styles$S.body,children:props.children}),placement:"right",children:jsxRuntimeExports.jsx(PhosphorIcon,{size:"small",icon:questionIcon,style:styles$S.spacingLeft})})};const styles$S=StyleSheet.create({spacingLeft:{marginInlineStart:spacing.xxxSmall_4},body:{padding:spacing.medium_16}});
1446
1447
 
1447
1448
  class InfoTip extends React.Component{componentDidMount(){this.setState({didMount:true});}render(){if(this.state.didMount){return jsxRuntimeExports.jsx(InfoTipBase,{...this.props})}return jsxRuntimeExports.jsx("div",{})}constructor(...args){super(...args),this.state={didMount:false};}}
1448
1449
 
1449
1450
  function TypedSingleSelect(props){const{options,onChange,placeholder,...rest}=props;return jsxRuntimeExports.jsx(SingleSelect,{...rest,placeholder:placeholder??"",onChange:onChange,children:Object.entries(options).map(([value,option])=>{if(typeof option==="object"&&option!==null){return jsxRuntimeExports.jsx(OptionItem,{value:value,label:option.label,leftAccessory:option.leftAccessory},value)}if(typeof option==="string"&&option!==""){return jsxRuntimeExports.jsx(OptionItem,{value:value,label:option},value)}return null})})}
1450
1451
 
1451
- function focusWithChromeStickyFocusBugWorkaround(element){element.focus({preventScroll:true});}const alignmentInfoMap={block:"Block - widget is constrained to the width of the article content container.","wrap-left":"Wrap left - widget is 50% width of the article content container, and is left aligned with text wrapping on the right of the widget.","wrap-right":"Wrap right - widget is 50% width of the article content container, and is right aligned with text wrapping on the left of the widget.","full-width":"Full width - widget extends beyond the width of the article content container."};
1452
+ const alignmentInfoMap={block:"Block - widget is constrained to the width of the article content container.","wrap-left":"Wrap left - widget is 50% width of the article content container, and is left aligned with text wrapping on the right of the widget.","wrap-right":"Wrap right - widget is 50% width of the article content container, and is right aligned with text wrapping on the left of the widget.","full-width":"Full width - widget extends beyond the width of the article content container."};
1452
1453
 
1453
- function AlignmentSelect({supportedAlignments,widgetInfo,isEditingDisabled,onChange,style}){const labelId=useId();return jsxRuntimeExports.jsxs(View,{style:[{flexDirection:"row",alignItems:"center",gap:sizing.size_080},style],children:[jsxRuntimeExports.jsx(BodyText,{id:labelId,tag:"span",children:"Alignment"}),jsxRuntimeExports.jsx(TypedSingleSelect,{"aria-labelledby":labelId,selectedValue:widgetInfo.alignment??"default",disabled:isEditingDisabled,options:{default:supportedAlignments.includes("default")&&"default",block:supportedAlignments.includes("block")&&"block","inline-block":supportedAlignments.includes("inline-block")&&"inline-block",inline:supportedAlignments.includes("inline")&&"inline","wrap-left":supportedAlignments.includes("wrap-left")&&"wrap-left","wrap-right":supportedAlignments.includes("wrap-right")&&"wrap-right","full-width":supportedAlignments.includes("full-width")&&"full-width"},onChange:onChange,placeholder:"Select alignment",style:styles$S.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("ul",{children:supportedAlignments.map((alignment,index)=>jsxRuntimeExports.jsx("li",{style:{marginBlockEnd:index<supportedAlignments.length-1?sizing.size_240:0},children:alignmentInfoMap[alignment]},alignment))})})]})}const styles$S=StyleSheet.create({singleSelectShort:{height:sizing.size_260}});
1454
+ function AlignmentSelect({supportedAlignments,widgetInfo,isEditingDisabled,onChange,style}){const labelId=useId();return jsxRuntimeExports.jsxs(View,{style:[{flexDirection:"row",alignItems:"center",gap:sizing.size_080},style],children:[jsxRuntimeExports.jsx(BodyText,{id:labelId,tag:"span",children:"Alignment"}),jsxRuntimeExports.jsx(TypedSingleSelect,{"aria-labelledby":labelId,selectedValue:widgetInfo.alignment??"default",disabled:isEditingDisabled,options:{default:supportedAlignments.includes("default")&&"default",block:supportedAlignments.includes("block")&&"block","inline-block":supportedAlignments.includes("inline-block")&&"inline-block",inline:supportedAlignments.includes("inline")&&"inline","wrap-left":supportedAlignments.includes("wrap-left")&&"wrap-left","wrap-right":supportedAlignments.includes("wrap-right")&&"wrap-right","full-width":supportedAlignments.includes("full-width")&&"full-width"},onChange:onChange,placeholder:"Select alignment",style:styles$R.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("ul",{children:supportedAlignments.map((alignment,index)=>jsxRuntimeExports.jsx("li",{style:{marginBlockEnd:index<supportedAlignments.length-1?sizing.size_240:0},children:alignmentInfoMap[alignment]},alignment))})})]})}const styles$R=StyleSheet.create({singleSelectShort:{height:sizing.size_260}});
1454
1455
 
1455
1456
  function WidgetEditorSettings(props){const{bestPractices,supportsStaticMode,isStatic,onStaticChange,supportsGradedToggle,isGraded,onGradedChange,supportedAlignments,widgetInfo,onAlignmentChange,isEditingDisabled}=props;const hasControls=supportsStaticMode||supportsGradedToggle||supportedAlignments.length>1;if(!bestPractices&&!hasControls){return null}return jsxRuntimeExports.jsxs(View,{className:"widget-editor-settings-container",children:[bestPractices&&jsxRuntimeExports.jsx(View,{className:"best-practices-container",children:jsxRuntimeExports.jsx(Link,{href:bestPractices.url,target:"_blank",children:bestPractices.label})}),hasControls&&jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[supportsStaticMode&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"Static",checked:isStatic,disabled:isEditingDisabled,onChange:onStaticChange,style:{marginBlockEnd:sizing.size_060}}),supportsGradedToggle&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"Interactive but ungraded",checked:!isGraded,disabled:isEditingDisabled,onChange:e=>{onGradedChange(!e);},style:{marginBlockEnd:sizing.size_060}}),supportedAlignments.length>1&&jsxRuntimeExports.jsx(AlignmentSelect,{supportedAlignments:supportedAlignments,widgetInfo:widgetInfo,isEditingDisabled:isEditingDisabled,onChange:onAlignmentChange,style:{marginBlockEnd:sizing.size_060}})]})]})}
1456
1457
 
@@ -1484,7 +1485,7 @@ katex.__defineMacro("\\ce",function(context){return chemParse(context.consumeArg
1484
1485
 
1485
1486
  const MATHJAX_ONLY_MACROS={"\\gold":"{#1}","\\inte":"\\int","\\RR":"\\mathbb{R}","\\AA":"A","\\^":"{#1}","\\lcm":"\\operatorname{lcm}","\\gcf":"\\operatorname{gcf}","\\arraystretch":""};function detectTexErrors(content){const errors=[];const ast=PerseusMarkdown.parse(content,{});PerseusMarkdown.traverseContent(ast,node=>{if(node.type==="math"||node.type==="blockMath"){const texContent=preprocessTex(node.content);try{katex.renderToString(texContent,{colorIsTextColor:true,macros:{...MATHJAX_ONLY_MACROS}});}catch(e){errors.push({math:texContent,message:e.message});}}});return errors}
1486
1487
 
1487
- const{HUD: HUD$1}=components;class ArticleEditor extends React.Component{componentDidMount(){this._updateIssues();}componentDidUpdate(prevProps){if(prevProps.json!==this.props.json){this._updateIssues();}}_updateIssues(){const issues=this._sections().map(section=>{const parsed=PerseusMarkdown.parse(section.content??"",{});const linterContext={content:section.content,widgets:section.widgets,stack:[]};const sectionIssues=PerseusLinter.runLinter(parsed,linterContext,false)?.map(linterWarning=>{if(linterWarning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(linterWarning.metadata?.widgetType??"unknown",linterWarning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(linterWarning.rule,linterWarning.message,linterWarning.severity)})??[];const texErrors=detectTexErrors(section.content??"");const texIssues=texErrors.map((error,index)=>WARNINGS.texError(error.math,error.message,index));return [...texIssues,...sectionIssues]});this.setState({issues});}_previewDataForSection(section,sectionIndex){const editor=this.refs[`editor${sectionIndex}`];return {article:section,apiOptions:this._apiOptionsForPreview(),linterContext:{contentType:"article",highlightLint:this.state.highlightLint},legacyPerseusLint:editor?.getSaveWarnings()??[]}}_apiOptionsForPreview(){return {...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true}}_sections(){const json=this.props.json;return json instanceof Array?json:[json]}_renderEditor(){const{imageUploader,sectionImageUploadGenerator}=this.props;const apiOptions={...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true};const sections=this._sections();const editingDisabled=this.props.apiOptions?.editingDisabled??false;const isMobile=this._isMobilePreview();return jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[sections.map((section,i)=>{return [jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("fieldset",{disabled:editingDisabled,children:[jsxRuntimeExports.jsx(IssuesPanel,{issues:this.state.issues[i]}),jsxRuntimeExports.jsxs("div",{className:"pod-title",children:["Section ",i+1,jsxRuntimeExports.jsxs("div",{style:{display:"inline-block",float:"inline-end"},children:[sectionImageUploadGenerator(i),jsxRuntimeExports.jsx(SectionControlButton,{icon:plusIcon,disabled:editingDisabled,onClick:()=>{this._handleAddSectionAfter(i);},title:"Add a new section after this one"}),i+1<sections.length&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleDownIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionLater(i);},title:"Move this section down"}),i>0&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleUpIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionEarlier(i);},title:"Move this section up"}),jsxRuntimeExports.jsx(SectionControlButton,{icon:trashIcon,disabled:editingDisabled,onClick:()=>{const msg="Are you sure you "+"want to delete section "+(i+1)+"?";if(confirm(msg)){this._handleRemoveSection(i);}},title:"Delete this section"})]})]}),jsxRuntimeExports.jsx(Editor,{...section,apiOptions:apiOptions,imageUploader:imageUploader,onChange:newProps=>this._handleEditorChange(i,newProps),placeholder:"Type your section text here...",ref:"editor"+i})]})}),jsxRuntimeExports.jsx("div",{className:"editor-preview",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:{type:"article-section",data:this._previewDataForSection(section,i)}},`${String(i)}-${this.props.screen}`)})})]},i)]}),this._renderAddSection(editingDisabled),this._renderLinterHUD()]})}_renderAddSection(editingDisabled){return jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,disabled:editingDisabled,kind:"tertiary","aria-label":"Add a section",onClick:()=>{this._handleAddSectionAfter(this._sections().length-1);},children:"Add a section"})})})}_renderLinterHUD(){return jsxRuntimeExports.jsx(HUD$1,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})}_renderPreviewMode(){return jsxRuntimeExports.jsx("div",{className:"standalone-preview",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:false,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:this._isMobilePreview(),seamless:false,url:this.props.previewURL,content:{type:"article-all",data:{article:this._sections(),apiOptions:this._apiOptionsForPreview()}}},`all-${this.props.screen}`)})})}_isMobilePreview(){return this.props.screen==="phone"||this.props.screen==="tablet"}_handleMoveSectionEarlier(i){if(i===0){return}const sections=[...this._sections()];const section=sections[i];sections.splice(i,1);sections.splice(i-1,0,section);this.props.onChange({json:sections});}_handleMoveSectionLater(i){const sections=[...this._sections()];if(i+1===sections.length){return}const section=sections[i];sections.splice(i,1);sections.splice(i+1,0,section);this.props.onChange({json:sections});}_handleAddSectionAfter(i){const clonedArticle=this.serialize();const sections=clonedArticle instanceof Array?clonedArticle:[clonedArticle];const newSection={content:"",images:{},widgets:i>=0?sections[i].widgets:{}};sections.splice(i+1,0,newSection);this.props.onChange({json:sections});}_handleRemoveSection(i){const sections=[...this._sections()];sections.splice(i,1);this.props.onChange({json:sections});}serialize(){if(this.props.mode==="edit"){return this._sections().map((section,i)=>{return this.refs["editor"+i].serialize()})}if(this.props.mode==="preview"||this.props.mode==="json"){return this.props.json}throw new PerseusError("Could not serialize; mode "+this.props.mode+" not found",Errors.Internal)}getSaveWarnings(){if(this.props.mode!=="edit"){throw new PerseusError("Can only get save warnings in edit mode.",Errors.NotAllowed)}return this._sections().map((section,i)=>{return this.refs["editor"+i].getSaveWarnings()})}render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus wb-themed-math perseus-article-editor",children:[this.props.mode==="edit"&&this._renderEditor(),this.props.mode==="preview"&&this._renderPreviewMode(),this.props.mode==="json"&&jsxRuntimeExports.jsxs("div",{className:"json-editor",children:[jsxRuntimeExports.jsx("div",{className:"json-editor-warning",children:jsxRuntimeExports.jsx("span",{children:"Warning: Editing in this mode can lead to broken articles!"})}),jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,onChange:this._handleJsonChange,value:this.props.json,parser:parseAndMigratePerseusArticle,editingDisabled:editingDisabled})]})]})})}constructor(...args){super(...args),this.state={highlightLint:true,issues:[]},this._handleJsonChange=newJson=>{this.props.onChange({json:newJson});},this._handleEditorChange=(i,newProps)=>{const sections=[...this._sections()];sections[i]={...sections[i],...newProps};this.props.onChange({json:sections});};}}ArticleEditor.defaultProps={json:[{content:"",widgets:{},images:{}}],mode:"edit",screen:"desktop",sectionImageUploadGenerator:()=>jsxRuntimeExports.jsx("span",{})};
1488
+ const{HUD: HUD$1}=components;class ArticleEditor extends React.Component{componentDidMount(){this._updateIssues();}componentDidUpdate(prevProps){if(prevProps.json!==this.props.json){this._updateIssues();}}_updateIssues(){const issues=this._sections().map(section=>{const parsed=PerseusMarkdown.parse(section.content??"",{});const linterContext={content:section.content,widgets:section.widgets,stack:[]};const sectionIssues=PerseusLinter.runLinter(parsed,linterContext,false)?.map(linterWarning=>{if(linterWarning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(linterWarning.metadata?.widgetType??"unknown",linterWarning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(linterWarning.rule,linterWarning.message,linterWarning.severity)})??[];const texErrors=detectTexErrors(section.content??"");const texIssues=texErrors.map((error,index)=>WARNINGS.texError(error.math,error.message,index));return [...texIssues,...sectionIssues]});this.setState({issues});}_previewDataForSection(section,sectionIndex){const editor=this.refs[`editor${sectionIndex}`];return {article:section,apiOptions:this._apiOptionsForPreview(),linterContext:{contentType:"article",highlightLint:this.state.highlightLint},legacyPerseusLint:editor?.getSaveWarnings()??[]}}_apiOptionsForPreview(){return {...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true}}_sections(){const json=this.props.json;return json instanceof Array?json:[json]}_renderEditor(){const{imageUploader,sectionImageUploadGenerator}=this.props;const apiOptions={...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true};const sections=this._sections();const editingDisabled=this.props.apiOptions?.editingDisabled??false;const isMobile=this._isMobilePreview();return jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[sections.map((section,i)=>{return [jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("fieldset",{disabled:editingDisabled,children:[jsxRuntimeExports.jsx(IssuesPanel,{issues:this.state.issues[i]}),jsxRuntimeExports.jsxs("div",{className:"pod-title",children:["Section ",i+1,jsxRuntimeExports.jsxs("div",{style:{display:"inline-block",float:"inline-end"},children:[sectionImageUploadGenerator(i),jsxRuntimeExports.jsx(SectionControlButton,{icon:plusIcon,disabled:editingDisabled,onClick:()=>{this._handleAddSectionAfter(i);},title:"Add a new section after this one"}),i+1<sections.length&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleDownIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionLater(i);},title:"Move this section down"}),i>0&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleUpIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionEarlier(i);},title:"Move this section up"}),jsxRuntimeExports.jsx(SectionControlButton,{icon:trashIcon,disabled:editingDisabled,onClick:()=>{const msg="Are you sure you "+"want to delete section "+(i+1)+"?";if(confirm(msg)){this._handleRemoveSection(i);}},title:"Delete this section"})]})]}),jsxRuntimeExports.jsx(Editor,{...section,apiOptions:apiOptions,imageUploader:imageUploader,onChange:newProps=>this._handleEditorChange(i,newProps),placeholder:"Type your section text here...",ref:"editor"+i})]})}),jsxRuntimeExports.jsx("div",{className:"editor-preview",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:{type:"article-section",data:this._previewDataForSection(section,i)}},`${String(i)}-${this.props.screen}`)})})]},i)]}),this._renderAddSection(editingDisabled),this._renderLinterHUD()]})}_renderAddSection(editingDisabled){return jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,disabled:editingDisabled,kind:"tertiary","aria-label":"Add a section",onClick:()=>{this._handleAddSectionAfter(this._sections().length-1);},children:"Add a section"})})})}_renderLinterHUD(){return jsxRuntimeExports.jsx(HUD$1,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})}_renderPreviewMode(){return jsxRuntimeExports.jsx("div",{className:"standalone-preview",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:false,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:this._isMobilePreview(),seamless:false,url:this.props.previewURL,content:{type:"article-all",data:{article:this._sections(),apiOptions:this._apiOptionsForPreview()}}},`all-${this.props.screen}`)})})}_isMobilePreview(){return this.props.screen==="phone"||this.props.screen==="tablet"}_handleMoveSectionEarlier(i){if(i===0){return}const sections=[...this._sections()];const section=sections[i];sections.splice(i,1);sections.splice(i-1,0,section);this.props.onChange({json:sections});}_handleMoveSectionLater(i){const sections=[...this._sections()];if(i+1===sections.length){return}const section=sections[i];sections.splice(i,1);sections.splice(i+1,0,section);this.props.onChange({json:sections});}_handleAddSectionAfter(i){const clonedArticle=this.serialize();const sections=clonedArticle instanceof Array?clonedArticle:[clonedArticle];const newSection={content:"",images:{},widgets:i>=0?sections[i].widgets:{}};sections.splice(i+1,0,newSection);this.props.onChange({json:sections});}_handleRemoveSection(i){const sections=[...this._sections()];sections.splice(i,1);this.props.onChange({json:sections});}serialize(){if(this.props.mode==="edit"){return this._sections().map((section,i)=>{return this.refs["editor"+i].serialize()})}if(this.props.mode==="preview"||this.props.mode==="json"){return this.props.json}throw new PerseusError("Could not serialize; mode "+this.props.mode+" not found",Errors.Internal)}getSaveWarnings(){if(this.props.mode!=="edit"){throw new PerseusError("Can only get save warnings in edit mode.",Errors.NotAllowed)}return this._sections().map((section,i)=>{return this.refs["editor"+i].getSaveWarnings()})}render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus perseus-article-editor",children:[this.props.mode==="edit"&&this._renderEditor(),this.props.mode==="preview"&&this._renderPreviewMode(),this.props.mode==="json"&&jsxRuntimeExports.jsxs("div",{className:"json-editor",children:[jsxRuntimeExports.jsx("div",{className:"json-editor-warning",children:jsxRuntimeExports.jsx("span",{children:"Warning: Editing in this mode can lead to broken articles!"})}),jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,onChange:this._handleJsonChange,value:this.props.json,parser:parseAndMigratePerseusArticle,editingDisabled:editingDisabled})]})]})})}constructor(...args){super(...args),this.state={highlightLint:true,issues:[]},this._handleJsonChange=newJson=>{this.props.onChange({json:newJson});},this._handleEditorChange=(i,newProps)=>{const sections=[...this._sections()];sections[i]={...sections[i],...newProps};this.props.onChange({json:sections});};}}ArticleEditor.defaultProps={json:[{content:"",widgets:{},images:{}}],mode:"edit",screen:"desktop",sectionImageUploadGenerator:()=>jsxRuntimeExports.jsx("span",{})};
1488
1489
 
1489
1490
  const iconChevronRight={path:"M62.808 49.728q0 3.36-2.352 5.88l-41.72 41.664q-2.352 2.408-5.768 2.408t-5.768-2.408l-4.872-4.76q-2.352-2.52-2.352-5.88t2.352-5.712l31.08-31.136-31.08-31.024q-2.352-2.52-2.352-5.88t2.352-5.712l4.872-4.76q2.296-2.408 5.768-2.408t5.768 2.408l41.72 41.664q2.352 2.296 2.352 5.656z",width:63.034,height:100};const iconCircleArrowDown={path:"M50.046 83.676q1.767 0 2.907-1.14l29.526-29.526q1.197-1.197 1.197-2.907t-1.197-2.964l-5.928-5.928q-1.197-1.14-2.964-1.14t-2.907 1.14l-12.312 12.312l0-32.661q0-1.71-1.254-2.964t-2.907-1.254l-8.322 0q-1.71 0-2.964 1.254t-1.254 2.964l0 32.661l-12.312-12.312q-1.197-1.254-2.907-1.254t-2.907 1.254l-5.928 5.928q-1.197 1.197-1.197 2.964t1.197 2.907l29.469 29.526q1.197 1.14 2.964 1.14zm49.989-33.63q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",width:100,height:100};const iconCircleArrowUp={path:"M54.207 83.391q1.653 0 2.907-1.254t1.254-2.907l0-32.718l12.312 12.312q1.254 1.254 2.964 1.254t2.907-1.254l5.928-5.928q1.197-1.197 1.14-2.964 0-1.767-1.14-2.907l-29.526-29.526q-1.197-1.14-2.907-1.14t-2.964 1.14l-29.469 29.526q-1.197 1.254-1.197 2.964t1.197 2.907l5.928 5.928q1.197 1.197 2.907 1.197t2.907-1.197l12.312-12.312l0 32.718q0 1.653 1.254 2.907t2.964 1.254l8.322 0zm45.828-33.345q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",width:100,height:100};const iconDesktop={path:"M94.208 52.119l0-43.746q0-.69-.506-1.15t-1.196-.506l-84.088 0q-.69 0-1.196.506t-.506 1.15l0 43.746q0 .69.506 1.196t1.196.506l84.088 0q.69 0 1.196-.506t.506-1.196zm6.716-43.746l0 57.224q0 3.45-2.484 5.934t-5.934 2.484l-28.566 0q0 3.128 2.53 7.774.828 1.61.828 2.622t-1.012 2.07q-1.012 1.012-2.346.966l-26.91 0q-1.38 0-2.392-1.012t-1.012-2.024q0-1.058 1.656-4.14t1.748-6.256l-28.612 0q-3.45 0-5.934-2.484t-2.484-5.934l0-57.224q0-3.45 2.484-5.934t5.934-2.438l84.088 0q3.45 0 5.98 2.438 2.438 2.484 2.438 5.934z",width:100,height:86.648};const iconMobilePhone={path:"M36.04 89.557q0-2.584-1.836-4.42t-4.42-1.836-4.352 1.836q-1.836 1.836-1.836 4.42t1.836 4.352 4.42 1.836q2.652-.068 4.42-1.836t1.768-4.352zm16.184-12.444l0-54.74q0-1.088-.748-1.768t-1.768-.68l-39.78 0q-1.088 0-1.768.748t-.68 1.7l0 54.74q0 1.02.748 1.768t1.7.68l39.78 0q1.02-.068 1.768-.748t.748-1.7zm-14.892-65.892q0-1.224-1.292-1.292l-12.444 0q-1.224.068-1.224 1.292t1.224 1.224l12.444 0q1.292 0 1.292-1.224zm22.372-1.292l0 79.628q0 3.944-2.992 6.936t-7.004 2.992l-39.78 0q-4.012 0-7.004-2.924-2.924-2.924-2.924-7.004l0-79.628q0-4.012 2.924-6.936t7.004-2.992l39.78 0q4.012-.068 7.004 2.924t2.992 7.004z",width:60.013,height:100};const iconTablet={path:"M45.322 90.706q0-1.86-1.302-3.224-1.364-1.364-3.224-1.364t-3.224 1.364-1.302 3.224q0 1.86 1.364 3.224 1.302 1.364 3.162 1.302 1.86.062 3.224-1.302t1.302-3.224zm27.218-11.346l0-68.014q0-.93-.682-1.612t-1.55-.682l-58.962 0q-.93 0-1.612.682t-.682 1.612l0 68.014q0 .93.682 1.612t1.612.62l58.962 0q.992-.062 1.612-.682t.62-1.55zm9.114-68.014l0 77.066q0 4.65-3.348 7.998t-7.998 3.348l-58.962 0q-4.65 0-7.998-3.348t-3.348-7.998l0-77.066q0-4.65 3.348-7.998t7.998-3.348l58.962 0q4.65 0 7.998 3.348t3.348 7.998z",width:81.852,height:100};
1490
1491
 
@@ -1508,29 +1509,29 @@ class WidgetDiff extends React.Component{render(){const{after,before,title,type}
1508
1509
 
1509
1510
  const filterWidgetInfo=function(widgetInfo,showAlignmentOptions){if(widgetInfo==null){return undefined}const{alignment,options,type}=widgetInfo;const filteredWidgetInfo={options};if(showAlignmentOptions&&CoreWidgetRegistry.getSupportedAlignments(type).length>1){filteredWidgetInfo.alignment=alignment;}if(Widgets.supportsStaticMode(type)){filteredWidgetInfo.static=widgetInfo?.static??undefined;}return filteredWidgetInfo};class RendererDiff extends React.Component{render(){const{after,before,showAlignmentOptions,showSeparator,title}=this.props;let textDiff;let widgetsDiff=[];if(before?.content||after?.content){textDiff=jsxRuntimeExports.jsx(TextDiff,{before:before?.content,after:after?.content,title:title});}const beforeWidgets=Object.keys(before?.widgets??{}).filter(widget=>before?.content.includes(widget));const afterWidgets=Object.keys(after?.widgets??{}).filter(widget=>after?.content.includes(widget));if(beforeWidgets.length>0||afterWidgets.length>0){const widgets=_.union(beforeWidgets,afterWidgets);widgetsDiff=widgets.map(widget=>jsxRuntimeExports.jsx(WidgetDiff,{before:filterWidgetInfo(before?.widgets?.[widget],showAlignmentOptions),after:filterWidgetInfo(after?.widgets?.[widget],showAlignmentOptions),title:widget,type:(before?.widgets?.[widget]??{}).type||(after?.widgets?.[widget]??{}).type},widget));}return jsxRuntimeExports.jsxs("div",{children:[textDiff,widgetsDiff,showSeparator&&jsxRuntimeExports.jsx("div",{className:"diff-separator"})]})}}RendererDiff.defaultProps={after:{content:"",images:{},widgets:{}},before:{content:"",images:{},widgets:{}},showAlignmentOptions:false,showSeparator:false};
1510
1511
 
1511
- class ArticleDiff extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState(ArticleDiff._stateFromProps(nextProps));}render(){const{before,after}=this.state;const sectionCount=Math.max(before.length,after.length);const sections=_.times(sectionCount,n=>jsxRuntimeExports.jsx(RendererDiff,{before:n<before.length?before[n]:undefined,after:n<after.length?after[n]:undefined,title:`Section ${n+1}`,showAlignmentOptions:true,showSeparator:n<sectionCount-1},n));return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsx("div",{className:"framework-perseus wb-themed-math",children:sections})})}constructor(...args){super(...args),this.state=ArticleDiff._stateFromProps(this.props);}}ArticleDiff._stateFromProps=props=>{const{before,after}=props;return {before:Array.isArray(before)?before:[before],after:Array.isArray(after)?after:[after]}};
1512
+ class ArticleDiff extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState(ArticleDiff._stateFromProps(nextProps));}render(){const{before,after}=this.state;const sectionCount=Math.max(before.length,after.length);const sections=_.times(sectionCount,n=>jsxRuntimeExports.jsx(RendererDiff,{before:n<before.length?before[n]:undefined,after:n<after.length?after[n]:undefined,title:`Section ${n+1}`,showAlignmentOptions:true,showSeparator:n<sectionCount-1},n));return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsx("div",{className:"framework-perseus",children:sections})})}constructor(...args){super(...args),this.state=ArticleDiff._stateFromProps(this.props);}}ArticleDiff._stateFromProps=props=>{const{before,after}=props;return {before:Array.isArray(before)?before:[before],after:Array.isArray(after)?after:[after]}};
1512
1513
 
1513
1514
  class AnswerAreaDiff extends React.Component{render(){const{after,before,title}=this.props;const diff=performDiff(before?before:{},after?after:{});return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("div",{className:"diff-header",children:title}),jsxRuntimeExports.jsx("div",{className:"diff-header",children:title}),jsxRuntimeExports.jsx("div",{className:"diff-body ui-helper-clearfix",children:jsxRuntimeExports.jsx(DiffEntry,{entry:diff})})]})}}
1514
1515
 
1515
- class ItemDiff extends React.Component{render(){const{before,after}=this.props;const hintCount=Math.max(before.hints.length,after.hints.length);const question=jsxRuntimeExports.jsx(RendererDiff,{before:before.question,after:after.question,title:"Question",showAlignmentOptions:false,showSeparator:true});const extras=jsxRuntimeExports.jsx(AnswerAreaDiff,{before:before.answerArea?before.answerArea:undefined,after:after.answerArea?after.answerArea:undefined,title:"Question extras"});const hints=_.times(hintCount,function(n){return jsxRuntimeExports.jsx(RendererDiff,{before:n<before.hints.length?before.hints[n]:undefined,after:n<after.hints.length?after.hints[n]:undefined,title:`Hint ${n+1}`,showAlignmentOptions:false,showSeparator:n<hintCount-1},n)});return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus wb-themed-math",children:[question,extras,hints.length>0&&jsxRuntimeExports.jsx("div",{className:"diff-separator"}),hints]})})}}
1516
+ class ItemDiff extends React.Component{render(){const{before,after}=this.props;const hintCount=Math.max(before.hints.length,after.hints.length);const question=jsxRuntimeExports.jsx(RendererDiff,{before:before.question,after:after.question,title:"Question",showAlignmentOptions:false,showSeparator:true});const extras=jsxRuntimeExports.jsx(AnswerAreaDiff,{before:before.answerArea?before.answerArea:undefined,after:after.answerArea?after.answerArea:undefined,title:"Question extras"});const hints=_.times(hintCount,function(n){return jsxRuntimeExports.jsx(RendererDiff,{before:n<before.hints.length?before.hints[n]:undefined,after:n<after.hints.length?after.hints[n]:undefined,title:`Hint ${n+1}`,showAlignmentOptions:false,showSeparator:n<hintCount-1},n)});return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus",children:[question,extras,hints.length>0&&jsxRuntimeExports.jsx("div",{className:"diff-separator"}),hints]})})}}
1516
1517
 
1517
1518
  class HintEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize HintEditor with no Editor");return {...this.editor.current.serialize(),replace:this.props.replace??undefined}}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor "+this.props.className,children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,apiOptions:this.props.apiOptions,widgets:this.props.widgets||undefined,content:this.props.content||undefined,images:this.props.images,placeholder:"Type your hint here...",imageUploader:this.props.imageUploader,onChange:this.props.onChange,widgetIsOpen:this.props.widgetIsOpen},this.props.itemId),this.props.isLast&&jsxRuntimeExports.jsx(BodyText,{size:"xsmall",children:"The last hint is automatically bolded."}),jsxRuntimeExports.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[this.props.showMoveButtons&&jsxRuntimeExports.jsxs("div",{className:"reorder-hints",children:[jsxRuntimeExports.jsx(IconButton,{icon:arrowCircleDownIcon,size:"small",kind:"tertiary",onClick:_.partial(this.props.onMove,1),disabled:this.props.isLast}),jsxRuntimeExports.jsx(IconButton,{icon:arrowCircleUpIcon,size:"small",kind:"tertiary",onClick:_.partial(this.props.onMove,-1),disabled:this.props.isFirst})]}),jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.replace,onChange:newCheckedState=>{this.props.onChange({replace:newCheckedState});},label:"Replace previous hint",style:{display:"inline-block"}})]}),this.props.showRemoveButton&&jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,size:"small",kind:"tertiary",disabled:this.props.apiOptions?.editingDisabled,onClick:this.props.onRemove,style:{marginInlineStart:"auto",display:"flex"},children:"Remove this hint"})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.handleReplaceChanged=e=>{this.props.onChange({replace:e.target.checked});},this.focus=()=>{this.editor.current?.focus();},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()};}}HintEditor.defaultProps={className:"",content:"",replace:false,showMoveButtons:true,showTitle:true,showRemoveButton:true};class CombinedHintEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize CombinedHintEditor with no HintEditor");return this.editor.current.serialize()}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";return jsxRuntimeExports.jsxs("div",{className:"perseus-combined-hint-editor "+"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(HintEditor,{ref:this.editor,itemId:this.props.itemId,isFirst:this.props.isFirst,isLast:this.props.isLast,widgets:this.props.hint.widgets,content:this.props.hint.content,images:this.props.hint.images,replace:this.props.hint.replace,imageUploader:this.props.imageUploader,onChange:this.props.onChange,onRemove:this.props.onRemove,onMove:this.props.onMove,apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:{type:"hint",data:{hint:this.props.hint,pos:this.props.pos,apiOptions:this.props.apiOptions||ApiOptions.defaults,linterContext:{contentType:"hint",highlightLint:this.props.highlightLint}}}})})})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.focus=()=>{this.editor.current?.focus();};}}class CombinedHintsEditor extends React.Component{handleHintChange(i,newProps){const hints=[...this.props.hints];hints[i]=_.extend({},this.serializeHint(i),newProps);this.props.onChange({hints:hints});}handleHintRemove(i){if(!confirm("Are you sure you want to delete this hint?")){return}const hints=[...this.props.hints];hints.splice(i,1);this.props.onChange({hints:hints});}handleHintMove(i,dir){const hints=[...this.props.hints];const hint=hints.splice(i,1)[0];hints.splice(i+dir,0,hint);this.props.onChange({hints:hints});}serialize(){return this.props.hints.map((_,i)=>this.serializeHint(i))}serializeHint(index){return this.refs["hintEditor"+index].serialize()}render(){const{itemId,hints}=this.props;const editingDisabled=this.props.apiOptions?.editingDisabled??false;const hintElems=hints.map((hint,i)=>{return jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(CombinedHintEditor,{ref:"hintEditor"+i,isFirst:i===0,isLast:i+1===hints.length,itemId:itemId,hint:hint,pos:i,imageUploader:this.props.imageUploader,onChange:this.handleHintChange.bind(this,i),onRemove:this.handleHintRemove.bind(this,i),onMove:this.handleHintMove.bind(this,i),deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,highlightLint:this.props.highlightLint,previewURL:this.props.previewURL,widgetIsOpen:this.props.widgetIsOpen})},"hintEditor"+i)});return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[hintElems,jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,disabled:editingDisabled,size:"small",onClick:this.addHint,children:"Add a hint"})})]})}constructor(...args){super(...args),this.addHint=()=>{const hint={content:"",images:{},widgets:{}};const hints=[...this.props.hints,hint];this.props.onChange({hints:hints});},this.getSaveWarnings=()=>{return _.chain(this.props.hints).map((hint,i)=>{return _.map(this.refs["hintEditor"+i].getSaveWarnings(),issue=>"Hint "+(i+1)+": "+issue)}).flatten(true).value()};}}CombinedHintsEditor.HintEditor=HintEditor;CombinedHintsEditor.defaultProps={hints:[],onChange:()=>{}};
1518
1519
 
1519
- const calculatorVariants=[{label:"Scientific calculator",variant:"scientific"},{label:"Graphing calculator",variant:"graphing"},{label:"Four-function calculator",variant:"four_function"}];class ItemExtrasEditor extends React.Component{shouldShowCalculatorVariants(){return this.props.calculatorVariant!==undefined}shouldShowFinancialCalculatorOptions(){return this.props.financialCalculatorMonthlyPayment||this.props.financialCalculatorTotalAmount||this.props.financialCalculatorTimeToPayOff}serialize(){const data={...ItemExtrasEditor.defaultProps};for(const key of ItemExtras){data[key]=!!this.props[key];}data.calculatorVariant=this.props.calculatorVariant;return data}render(){const{editingDisabled,calculatorVariant}=this.props;return jsxRuntimeExports.jsx("div",{className:"perseus-answer-editor",children:jsxRuntimeExports.jsxs("div",{className:"perseus-answer-options",children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show calculator",disabled:editingDisabled,infoTip:"Use the calculator when completing difficult calculations is NOT the intent of the question. DON’T use the calculator when testing the student’s ability to complete different types of computations.",checked:this.shouldShowCalculatorVariants(),onChange:newCheckedState=>{this.props.onChange({calculator:newCheckedState,calculatorVariant:newCheckedState?"scientific":undefined});}}),isFeatureOn(this.props,"desmos-calculator")&&calculatorVariant!==undefined&&jsxRuntimeExports.jsx(RadioGroup,{groupName:"calculator-variant",selectedValue:calculatorVariant,onChange:this.handleVariantChange,style:styles$R.indented,children:calculatorVariants.map((calcVariant,_)=>jsxRuntimeExports.jsx(Choice,{value:calcVariant.variant,label:calcVariant.label,disabled:editingDisabled,style:styles$R.calculatorChoice},calcVariant.variant))}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show financial calculator",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a financial calculator, e.g., for answering financial questions. Once checked, requires at least one of the three options below to be checked.",checked:this.shouldShowFinancialCalculatorOptions(),onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState,financialCalculatorTotalAmount:newCheckedState,financialCalculatorTimeToPayOff:newCheckedState});}}),this.shouldShowFinancialCalculatorOptions()&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include monthly payment",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a monthly payment calculator; e.g., given a loan amount, interest rate, and term, what is the monthly payment?",checked:this.props.financialCalculatorMonthlyPayment,onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include total amount",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a total amount calculator; e.g., given a monthly payment, interest rate, and term, what is the total amount to be paid?",checked:this.props.financialCalculatorTotalAmount,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTotalAmount:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include time-to-pay-off",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a time to pay off calculator; e.g., given a loan amount, interest rate, and monthly payment, how long will it take to pay off the loan?",checked:this.props.financialCalculatorTimeToPayOff,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTimeToPayOff:newCheckedState});},indent:true})]}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show periodic table",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a periodic table of the elements, e.g., for answering chemistry questions.",checked:this.props.periodicTable,onChange:newCheckedState=>{this.props.onChange({periodicTable:newCheckedState,periodicTableWithKey:false});}}),this.props.periodicTable&&jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include key/legend with periodic table",disabled:editingDisabled,infoTip:"Include a key for HS courses; omit for AP chemistry.",checked:this.props.periodicTableWithKey,onChange:newCheckedState=>{this.props.onChange({periodicTableWithKey:newCheckedState});},indent:true})]})})}constructor(...args){super(...args),this.handleVariantChange=newVariant=>{const selected=calculatorVariants.find(({variant})=>variant===newVariant);if(selected){this.props.onChange({calculatorVariant:selected.variant});}};}}ItemExtrasEditor.defaultProps=getDefaultAnswerArea();const ItemExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$R.checkbox,props.indent?styles$R.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{disabled:props.disabled,label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$R=StyleSheet.create({indented:{marginInlineStart:spacing.large_24},calculatorChoice:{marginBlock:sizing.size_010}});
1520
+ const calculatorVariants=[{label:"Scientific calculator",variant:"scientific"},{label:"Graphing calculator",variant:"graphing"},{label:"Four-function calculator",variant:"four_function"}];class ExtrasEditor extends React.Component{shouldShowCalculatorVariants(){return this.props.calculatorVariant!==undefined}shouldShowFinancialCalculatorOptions(){return this.props.financialCalculatorMonthlyPayment||this.props.financialCalculatorTotalAmount||this.props.financialCalculatorTimeToPayOff}serialize(){const data={...ExtrasEditor.defaultProps};for(const key of ItemExtras){data[key]=!!this.props[key];}data.calculatorVariant=this.props.calculatorVariant;return data}render(){const{editingDisabled,calculatorVariant}=this.props;return jsxRuntimeExports.jsx("div",{className:"perseus-answer-editor",children:jsxRuntimeExports.jsxs("div",{className:"perseus-answer-options",children:[jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Show calculator",disabled:editingDisabled,infoTip:"Use the calculator when completing difficult calculations is NOT the intent of the question. DON’T use the calculator when testing the student’s ability to complete different types of computations.",checked:this.shouldShowCalculatorVariants(),onChange:newCheckedState=>{this.props.onChange({calculator:newCheckedState,calculatorVariant:newCheckedState?"scientific":undefined});}}),isFeatureOn(this.props,"desmos-calculator")&&calculatorVariant!==undefined&&jsxRuntimeExports.jsx(RadioGroup,{groupName:"calculator-variant",selectedValue:calculatorVariant,onChange:this.handleVariantChange,style:styles$Q.indented,children:calculatorVariants.map((calcVariant,_)=>jsxRuntimeExports.jsx(Choice,{value:calcVariant.variant,label:calcVariant.label,disabled:editingDisabled,style:styles$Q.calculatorChoice},calcVariant.variant))}),jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Show financial calculator",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a financial calculator, e.g., for answering financial questions. Once checked, requires at least one of the three options below to be checked.",checked:this.shouldShowFinancialCalculatorOptions(),onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState,financialCalculatorTotalAmount:newCheckedState,financialCalculatorTimeToPayOff:newCheckedState});}}),this.shouldShowFinancialCalculatorOptions()&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Include monthly payment",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a monthly payment calculator; e.g., given a loan amount, interest rate, and term, what is the monthly payment?",checked:this.props.financialCalculatorMonthlyPayment,onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Include total amount",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a total amount calculator; e.g., given a monthly payment, interest rate, and term, what is the total amount to be paid?",checked:this.props.financialCalculatorTotalAmount,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTotalAmount:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Include time-to-pay-off",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a time to pay off calculator; e.g., given a loan amount, interest rate, and monthly payment, how long will it take to pay off the loan?",checked:this.props.financialCalculatorTimeToPayOff,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTimeToPayOff:newCheckedState});},indent:true})]}),jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Show periodic table",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a periodic table of the elements, e.g., for answering chemistry questions.",checked:this.props.periodicTable,onChange:newCheckedState=>{this.props.onChange({periodicTable:newCheckedState,periodicTableWithKey:false});}}),this.props.periodicTable&&jsxRuntimeExports.jsx(ExtraCheckbox,{label:"Include key/legend with periodic table",disabled:editingDisabled,infoTip:"Include a key for HS courses; omit for AP chemistry.",checked:this.props.periodicTableWithKey,onChange:newCheckedState=>{this.props.onChange({periodicTableWithKey:newCheckedState});},indent:true})]})})}constructor(...args){super(...args),this.handleVariantChange=newVariant=>{const selected=calculatorVariants.find(({variant})=>variant===newVariant);if(selected){this.props.onChange({calculatorVariant:selected.variant});}};}}ExtrasEditor.defaultProps=getDefaultAnswerArea();const ExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$Q.checkbox,props.indent?styles$Q.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{disabled:props.disabled,label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$Q=StyleSheet.create({indented:{marginInlineStart:spacing.large_24},calculatorChoice:{marginBlock:sizing.size_010}});
1520
1521
 
1521
1522
  function legacyPerseusLintEqual(a,b){return a.length===b.length&&a.every((warning,i)=>warning===b[i])}function inputsEqual(a,b){return a.question===b.question&&a.apiOptions===b.apiOptions&&a.deviceType===b.deviceType&&a.highlightLint===b.highlightLint&&a.problemNum===b.problemNum&&legacyPerseusLintEqual(a.legacyPerseusLint,b.legacyPerseusLint)}function buildContent(inputs){return {type:"question",data:{question:inputs.question,apiOptions:{...ApiOptions.defaults,...inputs.apiOptions,customKeypad:inputs.deviceType==="phone"||inputs.deviceType==="tablet"},linterContext:{contentType:"exercise",highlightLint:inputs.highlightLint},reviewMode:true,legacyPerseusLint:inputs.legacyPerseusLint,problemNum:inputs.problemNum}}}function createPreviewContentDeriver(){let lastInputs=null;let lastContent=null;return inputs=>{if(!inputs.question){return null}if(lastInputs&&inputsEqual(inputs,lastInputs)){return lastContent}const content=buildContent(inputs);lastInputs=inputs;lastContent=content;return content}}
1522
1523
 
1523
- class ItemEditor extends React.Component{serialize(){invariant(this.questionEditor.current,"cannot serialize ItemEditor without Editor");invariant(this.itemExtrasEditor.current,"cannot serialize ItemEditor without ItemExtrasEditor");invariant(this.hintsEditor.current,"cannot serialize ItemEditor without CombinedHintsEditor");return {question:this.questionEditor.current.serialize(),answerArea:this.itemExtrasEditor.current.serialize(),hints:this.hintsEditor.current.serialize()}}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";const editingDisabled=this.props.apiOptions?.editingDisabled??false;const a11yScanningEnabled=this.context?.a11yScanningEnabled??false;const highlightInstanceIds=this.context?.highlightInstanceIds??[];return jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-question-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question"}),jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(Editor,{ref:this.questionEditor,placeholder:"Type your question here...",className:"perseus-question-editor",imageUploader:this.props.imageUploader,onChange:this.handleEditorChange,apiOptions:this.props.apiOptions,showWordCount:true,widgetIsOpen:this.props.widgetIsOpen,additionalTemplates:this.props.additionalTemplates,...this.props.question},this.props.itemId)})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx("div",{id:"problemarea",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:this.derivePreviewContent({question:this.props.question,apiOptions:this.props.apiOptions,deviceType:this.props.deviceType,highlightLint:this.props.highlightLint,problemNum:this.props.problemNum,legacyPerseusLint:this.getSaveWarnings()??[]}),a11yScanningEnabled:a11yScanningEnabled,highlightInstanceIds:highlightInstanceIds,onA11yReport:this.handleA11yReport},this.props.deviceType)})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-answer-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question extras"}),jsxRuntimeExports.jsx(ItemExtrasEditor,{ref:this.itemExtrasEditor,apiOptions:this.props.apiOptions,onChange:this.handleItemExtrasChange,editingDisabled:editingDisabled,...this.props.answerArea})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell"})]}),jsxRuntimeExports.jsx(CombinedHintsEditor,{ref:this.hintsEditor,itemId:this.props.itemId,hints:this.props.hints,imageUploader:this.props.imageUploader,onChange:this.props.onChange,deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,previewURL:this.props.previewURL,highlightLint:this.props.highlightLint,widgetIsOpen:this.props.widgetIsOpen})]})}constructor(...args){super(...args),this.questionEditor=React.createRef(),this.itemExtrasEditor=React.createRef(),this.hintsEditor=React.createRef(),this.derivePreviewContent=createPreviewContentDeriver(),this.updateProps=newProps=>{const props=_(this.props).pick("question","answerArea");this.props.onChange(_(props).extend(newProps));},this.handleEditorChange=newProps=>{const question=_.extend({},this.props.question,newProps);this.updateProps({question});},this.handleItemExtrasChange=newProps=>{const answerArea=_.extend({},this.props.answerArea,newProps);this.updateProps({answerArea});},this.getSaveWarnings=()=>{return [...this.questionEditor.current?.getSaveWarnings()??[],...this.hintsEditor.current?.getSaveWarnings()??[]]},this.handleA11yReport=report=>{this.context?.onA11yReport(report);};}}ItemEditor.contextType=A11yContext;ItemEditor.defaultProps={onChange:()=>{},question:{},answerArea:{}};
1524
+ class ItemEditor extends React.Component{serialize(){invariant(this.questionEditor.current,"cannot serialize ItemEditor without Editor");invariant(this.extrasEditor.current,"cannot serialize ItemEditor without ExtrasEditor");invariant(this.hintsEditor.current,"cannot serialize ItemEditor without CombinedHintsEditor");return {question:this.questionEditor.current.serialize(),answerArea:this.extrasEditor.current.serialize(),hints:this.hintsEditor.current.serialize()}}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";const editingDisabled=this.props.apiOptions?.editingDisabled??false;const a11yScanningEnabled=this.context?.a11yScanningEnabled??false;const highlightInstanceIds=this.context?.highlightInstanceIds??[];return jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-question-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question"}),jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(Editor,{ref:this.questionEditor,placeholder:"Type your question here...",className:"perseus-question-editor",imageUploader:this.props.imageUploader,onChange:this.handleEditorChange,apiOptions:this.props.apiOptions,showWordCount:true,widgetIsOpen:this.props.widgetIsOpen,additionalTemplates:this.props.additionalTemplates,...this.props.question},this.props.itemId)})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx("div",{id:"problemarea",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(PreviewWithIframe,{isMobile:isMobile,seamless:true,url:this.props.previewURL,content:this.derivePreviewContent({question:this.props.question,apiOptions:this.props.apiOptions,deviceType:this.props.deviceType,highlightLint:this.props.highlightLint,problemNum:this.props.problemNum,legacyPerseusLint:this.getSaveWarnings()??[]}),a11yScanningEnabled:a11yScanningEnabled,highlightInstanceIds:highlightInstanceIds,onA11yReport:this.handleA11yReport},this.props.deviceType)})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-answer-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question extras"}),jsxRuntimeExports.jsx(ExtrasEditor,{ref:this.extrasEditor,apiOptions:this.props.apiOptions,onChange:this.handleExtrasChange,editingDisabled:editingDisabled,...this.props.answerArea})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell"})]}),jsxRuntimeExports.jsx(CombinedHintsEditor,{ref:this.hintsEditor,itemId:this.props.itemId,hints:this.props.hints,imageUploader:this.props.imageUploader,onChange:this.props.onChange,deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,previewURL:this.props.previewURL,highlightLint:this.props.highlightLint,widgetIsOpen:this.props.widgetIsOpen})]})}constructor(...args){super(...args),this.questionEditor=React.createRef(),this.extrasEditor=React.createRef(),this.hintsEditor=React.createRef(),this.derivePreviewContent=createPreviewContentDeriver(),this.updateProps=newProps=>{const props=_(this.props).pick("question","answerArea");this.props.onChange(_(props).extend(newProps));},this.handleEditorChange=newProps=>{const question=_.extend({},this.props.question,newProps);this.updateProps({question});},this.handleExtrasChange=newProps=>{const answerArea=_.extend({},this.props.answerArea,newProps);this.updateProps({answerArea});},this.getSaveWarnings=()=>{return [...this.questionEditor.current?.getSaveWarnings()??[],...this.hintsEditor.current?.getSaveWarnings()??[]]},this.handleA11yReport=report=>{this.context?.onA11yReport(report);};}}ItemEditor.contextType=A11yContext;ItemEditor.defaultProps={onChange:()=>{},question:{},answerArea:{}};
1524
1525
 
1525
1526
  function buildDeviceApiOptions(inputs){return {...ApiOptions.defaults,...inputs.apiOptions,customKeypad:inputs.touch,isMobile:inputs.touch}}function createDeviceApiOptionsDeriver(){let lastInputs=null;let lastResult=null;return inputs=>{if(lastResult!=null&&lastInputs!=null&&lastInputs.apiOptions===inputs.apiOptions&&lastInputs.touch===inputs.touch){return lastResult}const result=buildDeviceApiOptions(inputs);lastInputs=inputs;lastResult=result;return result}}
1526
1527
 
1527
1528
  function lintRenderer(content,widgets){const parsed=PerseusMarkdown.parse(content,{});const linterContext={content,widgets,stack:[]};const linterIssues=(PerseusLinter.runLinter(parsed,linterContext,false)??[]).map(warning=>{if(warning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(warning.metadata?.widgetType??"unknown",warning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(warning.rule,warning.message,warning.severity)});const texIssues=detectTexErrors(content).map((error,i)=>WARNINGS.texError(error.math,error.message,i));const ruleCounts=new Map;return [...linterIssues,...texIssues].map(issue=>{const ordinal=ruleCounts.get(issue.id)??0;ruleCounts.set(issue.id,ordinal+1);return {...issue,instanceId:issue.instanceId??`${issue.id}-${ordinal}`}})}function gatherLinterIssues(question,hints,hostIssues){const questionIssues=lintRenderer(question?.content??"",question?.widgets);const hintIssues=hints.flatMap((hint,i)=>lintRenderer(hint.content??"",hint.widgets??undefined).map(issue=>({...issue,id:`hint-${i+1}-${issue.id}`,instanceId:`hint-${i+1}-${getIssueKey(issue)}`,message:`Hint ${i+1}: ${issue.message}`})));return [...hostIssues??[],...questionIssues,...hintIssues]}
1528
1529
 
1529
- const{HUD}=components;class EditorPage extends React.Component{componentDidMount(){this.setState({issues:gatherLinterIssues(this.props.question,this.props.hints,this.props.issues)});}getSnapshotBeforeUpdate(prevProps){if(!prevProps.jsonMode&&this.props.jsonMode){return this.itemEditor.current?.serialize()??{}}return null}componentDidUpdate(previousProps,prevState,snapshot){if(snapshot){this.setState({json:snapshot});return}if(!_.isEqual(previousProps.question,this.props.question)||!_.isEqual(previousProps.answerArea,this.props.answerArea)||!_.isEqual(previousProps.hints,this.props.hints)){this.syncJsonStateFromProps();}const questionOrHintsChanged=previousProps.question?.content!==this.props.question?.content||previousProps.question?.widgets!==this.props.question?.widgets||!_.isEqual(previousProps.hints,this.props.hints);if(questionOrHintsChanged){this.setState({issues:gatherLinterIssues(this.props.question,this.props.hints,this.props.issues)});}}syncJsonStateFromProps(){this.setState({json:{question:this.props.question,answerArea:this.props.answerArea,hints:this.props.hints}});}getSaveWarnings(){return this.itemEditor.current?.getSaveWarnings()}serialize(){if(this.props.jsonMode){return this.state.json}invariant(this.itemEditor.current,"cannot serialize EditorPage without ItemEditor");return this.itemEditor.current.serialize()}render(){let className="framework-perseus wb-themed-math";const editingDisabled=this.props.apiOptions?.editingDisabled??false;const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions=this.deriveDeviceApiOptions({apiOptions:this.props.apiOptions,touch});const showEditor=!this.props.developerMode||!this.props.jsonMode;if(deviceBasedApiOptions.isMobile){className+=" "+ClassNames.MOBILE;}return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},children:jsxRuntimeExports.jsxs("div",{id:"perseus",className:className,children:[jsxRuntimeExports.jsxs("div",{style:{marginBlockEnd:10},children:[this.props.developerMode&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Developer JSON Mode:"," ",jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.jsonMode,disabled:this.props.apiOptions?.editingDisabled,onChange:this.toggleJsonMode})]})," "]}),!this.props.jsonMode&&jsxRuntimeExports.jsx(ViewportResizer,{deviceType:this.props.previewDevice,onViewportSizeChanged:this.props.onPreviewDeviceChange}),!this.props.jsonMode&&jsxRuntimeExports.jsx(HUD,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})]}),this.props.developerMode&&this.props.jsonMode&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,value:this.state.json,parser:parseAndMigratePerseusItem,onChange:this.changeJSON,editingDisabled:editingDisabled})}),jsxRuntimeExports.jsxs(A11yContext.Provider,{value:createA11yContextValue({setIssueHighlight:this.setIssueHighlight,a11yScanningEnabled:this.state.a11yScanningEnabled,setA11yScanningEnabled:this.setA11yScanningEnabled,highlightInstanceIds:this.state.highlightInstanceIds,onA11yReport:this.handleA11yReport,axeCoreIssues:this.state.axeCoreIssues}),children:[showEditor&&jsxRuntimeExports.jsx("div",{className:"perseus-editor-table",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(IssuesPanel,{issues:this.state.issues})})})}),showEditor&&jsxRuntimeExports.jsx(ItemEditor,{ref:this.itemEditor,itemId:this.props.itemId,question:this.props.question,hints:this.props.hints,answerArea:this.props.answerArea,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,widgetIsOpen:this.state.widgetsAreOpen,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,additionalTemplates:this.props.additionalTemplates,highlightLint:this.state.highlightLint,problemNum:this.props.problemNum})]})]})})})}constructor(props){super(props),this.itemEditor=React.createRef(),this.deriveDeviceApiOptions=createDeviceApiOptionsDeriver(),this.setIssueHighlight=(instanceId,highlighted)=>{this.setState(prevState=>{const current=prevState.highlightInstanceIds;if(highlighted===current.includes(instanceId)){return null}return {highlightInstanceIds:highlighted?[...current,instanceId]:current.filter(id=>id!==instanceId)}});},this.handleA11yReport=report=>{this.setState({axeCoreIssues:report?[...report.violations,...report.needsReview]:[]});},this.setA11yScanningEnabled=enabled=>{this.setState({a11yScanningEnabled:enabled});},this.toggleJsonMode=()=>{this.setState({json:this.serialize()},()=>{this.props.onChange({jsonMode:!this.props.jsonMode});});},this.handleChange=toChange=>{const newProps=_(this.props).pick("question","hints","answerArea");_(newProps).extend(toChange);this.props.onChange(newProps);},this.handleEditorChange=newProps=>{this.handleChange({question:{...this.props.question,...newProps}});},this.changeJSON=newJson=>{this.setState({json:newJson});this.props.onChange(newJson);};this.state={json:_.pick(this.props,"question","answerArea","hints"),highlightLint:true,widgetsAreOpen:this.props.widgetsAreOpen??true,issues:[],axeCoreIssues:[],a11yScanningEnabled:false,highlightInstanceIds:[]};}}EditorPage.defaultProps={answerArea:getDefaultAnswerArea(),developerMode:false,hints:[],jsonMode:false,onChange:()=>{}};
1530
+ const{HUD}=components;class EditorPage extends React.Component{componentDidMount(){this.setState({issues:gatherLinterIssues(this.props.question,this.props.hints,this.props.issues)});}getSnapshotBeforeUpdate(prevProps){if(!prevProps.jsonMode&&this.props.jsonMode){return this.itemEditor.current?.serialize()??{}}return null}componentDidUpdate(previousProps,prevState,snapshot){if(snapshot){this.setState({json:snapshot});return}if(!_.isEqual(previousProps.question,this.props.question)||!_.isEqual(previousProps.answerArea,this.props.answerArea)||!_.isEqual(previousProps.hints,this.props.hints)){this.syncJsonStateFromProps();}const questionOrHintsChanged=previousProps.question?.content!==this.props.question?.content||previousProps.question?.widgets!==this.props.question?.widgets||!_.isEqual(previousProps.hints,this.props.hints);if(questionOrHintsChanged){this.setState({issues:gatherLinterIssues(this.props.question,this.props.hints,this.props.issues)});}}syncJsonStateFromProps(){this.setState({json:{question:this.props.question,answerArea:this.props.answerArea,hints:this.props.hints}});}getSaveWarnings(){return this.itemEditor.current?.getSaveWarnings()}serialize(){if(this.props.jsonMode){return this.state.json}invariant(this.itemEditor.current,"cannot serialize EditorPage without ItemEditor");return this.itemEditor.current.serialize()}render(){let className="framework-perseus";const editingDisabled=this.props.apiOptions?.editingDisabled??false;const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions=this.deriveDeviceApiOptions({apiOptions:this.props.apiOptions,touch});const showEditor=!this.props.developerMode||!this.props.jsonMode;if(deviceBasedApiOptions.isMobile){className+=" "+ClassNames.MOBILE;}return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},children:jsxRuntimeExports.jsxs("div",{id:"perseus",className:className,children:[jsxRuntimeExports.jsxs("div",{style:{marginBlockEnd:10},children:[this.props.developerMode&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Developer JSON Mode:"," ",jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.jsonMode,disabled:this.props.apiOptions?.editingDisabled,onChange:this.toggleJsonMode})]})," "]}),!this.props.jsonMode&&jsxRuntimeExports.jsx(ViewportResizer,{deviceType:this.props.previewDevice,onViewportSizeChanged:this.props.onPreviewDeviceChange}),!this.props.jsonMode&&jsxRuntimeExports.jsx(HUD,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})]}),this.props.developerMode&&this.props.jsonMode&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,value:this.state.json,parser:parseAndMigratePerseusItem,onChange:this.changeJSON,editingDisabled:editingDisabled})}),jsxRuntimeExports.jsxs(A11yContext.Provider,{value:createA11yContextValue({setIssueHighlight:this.setIssueHighlight,a11yScanningEnabled:this.state.a11yScanningEnabled,setA11yScanningEnabled:this.setA11yScanningEnabled,highlightInstanceIds:this.state.highlightInstanceIds,onA11yReport:this.handleA11yReport,axeCoreIssues:this.state.axeCoreIssues}),children:[showEditor&&jsxRuntimeExports.jsx("div",{className:"perseus-editor-table",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(IssuesPanel,{issues:this.state.issues})})})}),showEditor&&jsxRuntimeExports.jsx(ItemEditor,{ref:this.itemEditor,itemId:this.props.itemId,question:this.props.question,hints:this.props.hints,answerArea:this.props.answerArea,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,widgetIsOpen:this.state.widgetsAreOpen,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,additionalTemplates:this.props.additionalTemplates,highlightLint:this.state.highlightLint,problemNum:this.props.problemNum})]})]})})})}constructor(props){super(props),this.itemEditor=React.createRef(),this.deriveDeviceApiOptions=createDeviceApiOptionsDeriver(),this.setIssueHighlight=(instanceId,highlighted)=>{this.setState(prevState=>{const current=prevState.highlightInstanceIds;if(highlighted===current.includes(instanceId)){return null}return {highlightInstanceIds:highlighted?[...current,instanceId]:current.filter(id=>id!==instanceId)}});},this.handleA11yReport=report=>{this.setState({axeCoreIssues:report?[...report.violations,...report.needsReview]:[]});},this.setA11yScanningEnabled=enabled=>{this.setState({a11yScanningEnabled:enabled});},this.toggleJsonMode=()=>{this.setState({json:this.serialize()},()=>{this.props.onChange({jsonMode:!this.props.jsonMode});});},this.handleChange=toChange=>{const newProps=_(this.props).pick("question","hints","answerArea");_(newProps).extend(toChange);this.props.onChange(newProps);},this.handleEditorChange=newProps=>{this.handleChange({question:{...this.props.question,...newProps}});},this.changeJSON=newJson=>{this.setState({json:newJson});this.props.onChange(newJson);};this.state={json:_.pick(this.props,"question","answerArea","hints"),highlightLint:true,widgetsAreOpen:this.props.widgetsAreOpen??true,issues:[],axeCoreIssues:[],a11yScanningEnabled:false,highlightInstanceIds:[]};}}EditorPage.defaultProps={answerArea:getDefaultAnswerArea(),developerMode:false,hints:[],jsonMode:false,onChange:()=>{}};
1530
1531
 
1531
1532
  let nextIframeID=0;const requestIframeData={};const updateIframeHeight={};window.iframeDataStore={};window.addEventListener("message",event=>{if(typeof event.data==="string"){const callback=requestIframeData[event.data];if(callback){callback();}}else if(event.data.id){if(event.data.height!==undefined){updateIframeHeight[event.data.id](event.data.height);}else if(event.data.lintWarnings){Log.log("LINTER REPORT",{lintWarnings:JSON.stringify(event.data.lintWarnings)});}}});class IframeContentRenderer extends React.Component{componentDidMount(){this._isMounted=true;this.iframeID=nextIframeID;nextIframeID++;this._prepareFrame();requestIframeData[this.iframeID]=()=>{this.sendNewData(this._lastData);};updateIframeHeight[this.iframeID]=height=>{this._lastHeight=height;if(this._isMounted&&this.props.seamless&&this.container.current){this.container.current.style.height=height+"px";}};}shouldComponentUpdate(nextProps){return nextProps.datasetValue!==this.props.datasetValue||nextProps.seamless!==this.props.seamless}componentDidUpdate(prevProps){if(this.container.current){if(!this.props.seamless){this.container.current.style.height="100%";}else {this.container.current.style.height=this._lastHeight+"px";}}if(prevProps.datasetValue!==this.props.datasetValue){this._prepareFrame();}}componentWillUnmount(){requestIframeData[this.iframeID]=null;updateIframeHeight[this.iframeID]=null;this._isMounted=false;}_prepareFrame(){if(this._frame){this.container.current?.removeChild(this._frame);}const frame=document.createElement("iframe");frame.style.width="100%";frame.style.height="100%";frame.dataset.name="content-preview";frame.src=this.props.url;frame.onload=()=>{const iframeDoc=frame.contentDocument||frame.contentWindow?.document;if(iframeDoc){const axeCoreScriptElement=iframeDoc.createElement("script");axeCoreScriptElement.src="https://unpkg.com/axe-core@4.11.0/axe.js";iframeDoc.body.appendChild(axeCoreScriptElement);}else {console.warn("Unable to add axe-core to iframe document");}};if(this.props.datasetKey){frame.dataset[this.props.datasetKey]=this.props.datasetValue;}frame.dataset.id=String(this.iframeID);if(this.props.seamless){frame.dataset.lintGutter="true";}this.container.current?.appendChild(frame);this._frame=frame;}sendNewData(data){const frame=this._frame;if(this._isMounted&&data&&frame?.contentWindow){this._lastData=data;window.iframeDataStore[this.iframeID]=data;frame.contentWindow.postMessage(this.iframeID,"*");}}render(){return jsxRuntimeExports.jsx("div",{ref:this.container,style:{width:"100%",height:"100%"}})}constructor(...args){super(...args),this.container=React.createRef();}}
1532
1533
 
1533
- function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice,reviewMode}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus wb-themed-math ${className}`,style:[styles$Q.container,!seamless?styles$Q.gutter:undefined],children:jsxRuntimeExports.jsx(StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(UserInputManager,{widgets:question?.widgets||{},problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,reviewMode:reviewMode,...question})}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$Q=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginInlineEnd:lintGutterWidth}});
1534
+ function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice,reviewMode}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus ${className}`,style:[styles$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(UserInputManager,{widgets:question?.widgets||{},problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,reviewMode:reviewMode,...question})}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$P=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginInlineEnd:lintGutterWidth}});
1534
1535
 
1535
1536
  var issuesList = {"axe-core":{"user-fixable":["aria-input-field-name","aria-meter-name","aria-toggle-field-name","image-alt","input-image-alt","label","link-name","list","role-img-alt","select-name","summary-name","svg-img-alt","video-caption"]}};
1536
1537
 
@@ -1546,76 +1547,76 @@ const USAGE="Usage:\n"+" this.change({propName: 5}, callback);\n"+' this.chang
1546
1547
 
1547
1548
  const EditorJsonify={serialize:function(){return excludeDenylistKeys(this.props)}};
1548
1549
 
1549
- const Categorizer=Categorizer$1.widget;class CategorizerEditor extends React.Component{render(){const categorizerProps={options:{items:this.props.items,categories:this.props.categories,randomizeItems:false,values:[]},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,{options:this.props.categories,onChange:cat=>{this.change("categories",cat);},layout:"horizontal"}),"Items:",jsxRuntimeExports.jsx(TextListEditor,{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 deprecatedChangeableChange.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}CategorizerEditor.widgetName="categorizer";CategorizerEditor.defaultProps=categorizerLogic.defaultWidgetOptions;
1550
+ const Categorizer=Categorizer$1.widget;class CategorizerEditor extends React.Component{render(){const categorizerProps={options:{items:this.props.items,categories:this.props.categories,randomizeItems:false,values:[]},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,{options:this.props.categories,onChange:cat=>{this.change("categories",cat);},layout:"horizontal"}),"Items:",jsxRuntimeExports.jsx(TextListEditor,{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 deprecatedChangeableChange.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}CategorizerEditor.defaultProps=categorizerLogic.defaultWidgetOptions;
1550
1551
 
1551
1552
  class BlurInput extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({value:nextProps.value});}focus(){this.input.current?.focus();}render(){return jsxRuntimeExports.jsx("input",{ref:this.input,className:this.props.className,style:this.props.style,type:"text",value:this.state.value,onChange:this.handleChange,onBlur:this.handleBlur})}constructor(props){super(props),this.input=React.createRef(),this.handleChange=e=>{this.setState({value:e.target.value});},this.handleBlur=e=>{this.props.onChange(e.target.value);};this.state={value:this.props.value};}}
1552
1553
 
1553
- const DEFAULT_WIDTH=400;const DEFAULT_HEIGHT=400;let PairEditor$1 = class PairEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("fieldset",{className:"pair-editor",children:[jsxRuntimeExports.jsxs("label",{children:["Name:"," ",jsxRuntimeExports.jsx(BlurInput,{value:this.props.name,onChange:this.change("name")})]}),jsxRuntimeExports.jsxs("label",{children:[" ","Value:"," ",jsxRuntimeExports.jsx(BlurInput,{value:this.props.value,onChange:this.change("value")})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}};PairEditor$1.defaultProps={name:"",value:""};let PairsEditor$1 = class PairsEditor extends React.Component{render(){const editors=this.props.pairs.map((pair,i)=>{return jsxRuntimeExports.jsx(PairEditor$1,{name:pair.name,value:pair.value,onChange:this.handlePairChange.bind(this,i)},i)});return jsxRuntimeExports.jsx("div",{children:editors})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handlePairChange=(pairIndex,pair)=>{const pairs=this.props.pairs.slice();pairs[pairIndex]=pair;const lastPair=pairs[pairs.length-1];if(lastPair.name&&lastPair.value){pairs.push({name:"",value:""});}this.change("pairs",pairs);};}};const KA_PROGRAM_URL=/khanacademy\.org\/computer-programming\/[^/]+\/(\d+)/;function isolateProgramID(programUrl){const match=KA_PROGRAM_URL.exec(programUrl);if(match){programUrl=match[1];}return programUrl}class CSProgramEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Url or Program ID:"," ",jsxRuntimeExports.jsx(BlurInput,{value:this.props.programID,onChange:this._handleProgramIDChange})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Show Editor",checked:this.props.showEditor,onChange:value=>{this.props.onChange({showEditor:value});}}),jsxRuntimeExports.jsx(InfoTip,{children:'If you show the editor, you should use the "full-width" alignment to make room for the width of the editor.'}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Show Buttons",checked:this.props.showButtons,onChange:value=>{this.props.onChange({showButtons:value});}}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Settings:",jsxRuntimeExports.jsx(PairsEditor$1,{pairs:this.props.settings,onChange:this._handleSettingsChange}),jsxRuntimeExports.jsxs(InfoTip,{children:["Settings that you add here are available to the program as an object returned by ",jsxRuntimeExports.jsx("code",{children:"Program.settings()"})]})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this._handleSettingsChange=settings=>{this.change({settings:settings.pairs});},this._handleProgramIDChange=programID=>{programID=isolateProgramID(programID);const{isDevServer,InitialRequestUrl}=Dependencies.getDependencies();const host=isDevServer?InitialRequestUrl.origin:"https://www.khanacademy.org";const baseUrl=`${host}/api/internal/scratchpads/${programID}`;const fetchProgramInfo=async()=>{const response=await fetch(baseUrl);if(!response.ok){throw new Error(`Request for scratchpad info failed with status ${response.status} ${response.statusText}`)}return response.json()};fetchProgramInfo().then(programInfo=>{const programType=programInfo.userAuthoredContentType;this.change({width:programInfo.width,height:programInfo.height,programID:programID,programType:programType});},error=>{Log.error("Error retrieving scratchpad info for program ID ",Errors.TransientService,{cause:error,loggedMetadata:{programID}});this.change({width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,programID:programID,programType:null});});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}CSProgramEditor.widgetName="cs-program";
1554
+ const DEFAULT_WIDTH=400;const DEFAULT_HEIGHT=400;let PairEditor$1 = class PairEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("fieldset",{className:"pair-editor",children:[jsxRuntimeExports.jsxs("label",{children:["Name:"," ",jsxRuntimeExports.jsx(BlurInput,{value:this.props.name,onChange:this.change("name")})]}),jsxRuntimeExports.jsxs("label",{children:[" ","Value:"," ",jsxRuntimeExports.jsx(BlurInput,{value:this.props.value,onChange:this.change("value")})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}};PairEditor$1.defaultProps={name:"",value:""};let PairsEditor$1 = class PairsEditor extends React.Component{render(){const editors=this.props.pairs.map((pair,i)=>{return jsxRuntimeExports.jsx(PairEditor$1,{name:pair.name,value:pair.value,onChange:this.handlePairChange.bind(this,i)},i)});return jsxRuntimeExports.jsx("div",{children:editors})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handlePairChange=(pairIndex,pair)=>{const pairs=this.props.pairs.slice();pairs[pairIndex]=pair;const lastPair=pairs[pairs.length-1];if(lastPair.name&&lastPair.value){pairs.push({name:"",value:""});}this.change("pairs",pairs);};}};const KA_PROGRAM_URL=/khanacademy\.org\/computer-programming\/[^/]+\/(\d+)/;function isolateProgramID(programUrl){const match=KA_PROGRAM_URL.exec(programUrl);if(match){programUrl=match[1];}return programUrl}class CSProgramEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Url or Program ID:"," ",jsxRuntimeExports.jsx(BlurInput,{value:this.props.programID,onChange:this._handleProgramIDChange})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Show Editor",checked:this.props.showEditor,onChange:value=>{this.props.onChange({showEditor:value});}}),jsxRuntimeExports.jsx(InfoTip,{children:'If you show the editor, you should use the "full-width" alignment to make room for the width of the editor.'}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Show Buttons",checked:this.props.showButtons,onChange:value=>{this.props.onChange({showButtons:value});}}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Settings:",jsxRuntimeExports.jsx(PairsEditor$1,{pairs:this.props.settings,onChange:this._handleSettingsChange}),jsxRuntimeExports.jsxs(InfoTip,{children:["Settings that you add here are available to the program as an object returned by ",jsxRuntimeExports.jsx("code",{children:"Program.settings()"})]})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this._handleSettingsChange=settings=>{this.change({settings:settings.pairs});},this._handleProgramIDChange=programID=>{programID=isolateProgramID(programID);const{isDevServer,InitialRequestUrl}=Dependencies.getDependencies();const host=isDevServer?InitialRequestUrl.origin:"https://www.khanacademy.org";const baseUrl=`${host}/api/internal/scratchpads/${programID}`;const fetchProgramInfo=async()=>{const response=await fetch(baseUrl);if(!response.ok){throw new Error(`Request for scratchpad info failed with status ${response.status} ${response.statusText}`)}return response.json()};fetchProgramInfo().then(programInfo=>{const programType=programInfo.userAuthoredContentType;this.change({width:programInfo.width,height:programInfo.height,programID:programID,programType:programType});},error=>{Log.error("Error retrieving scratchpad info for program ID ",Errors.TransientService,{cause:error,loggedMetadata:{programID}});this.change({width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,programID:programID,programType:null});});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}
1554
1555
 
1555
- const{TextInput: TextInput$5}=components;class DefinitionEditor extends React.Component{static initializeWidgetOptions(params){const defaultWidgetOptions={...definitionLogic.defaultWidgetOptions};if(params.selectedText){defaultWidgetOptions.togglePrompt=params.selectedText;}return defaultWidgetOptions}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-definition-editor",children:[jsxRuntimeExports.jsx("a",{href:"https://docs.google.com/document/d/1udaPef4imOfTMhmLDlWq4SM0mxL0r3YHFZE-5J1uGfo",target:"_blank",rel:"noreferrer",children:"Definition style guide"}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Word to be defined:"," ",jsxRuntimeExports.jsx(TextInput$5,{value:this.props.togglePrompt,onChange:this.change("togglePrompt"),placeholder:"define me"})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:this.props.definition,widgetEnabled:false,placeholder:"definition goes here",onChange:props=>{const newProps={};if(_.has(props,"content")){newProps.definition=props.content;}this.change(newProps);}})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}DefinitionEditor.widgetName="definition";DefinitionEditor.defaultProps=definitionLogic.defaultWidgetOptions;
1556
+ const{TextInput: TextInput$5}=components;class DefinitionEditor extends React.Component{static initializeWidgetOptions(params){const defaultWidgetOptions={...definitionLogic.defaultWidgetOptions};if(params.selectedText){defaultWidgetOptions.togglePrompt=params.selectedText;}return defaultWidgetOptions}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-definition-editor",children:[jsxRuntimeExports.jsx("a",{href:"https://docs.google.com/document/d/1udaPef4imOfTMhmLDlWq4SM0mxL0r3YHFZE-5J1uGfo",target:"_blank",rel:"noreferrer",children:"Definition style guide"}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Word to be defined:"," ",jsxRuntimeExports.jsx(TextInput$5,{value:this.props.togglePrompt,onChange:this.change("togglePrompt"),placeholder:"define me"})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:this.props.definition,widgetEnabled:false,placeholder:"definition goes here",onChange:props=>{const newProps={};if(_.has(props,"content")){newProps.definition=props.content;}this.change(newProps);}})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}DefinitionEditor.defaultProps=definitionLogic.defaultWidgetOptions;
1556
1557
 
1557
- class DeprecatedStandinEditor extends React.Component{serialize(){return EditorJsonify.serialize.call(this)}render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("p",{children:"This widget has been deprecated and removed"}),jsxRuntimeExports.jsx("p",{children:"Learners will see a message and they will not be graded on this part. Please replace this widget with a supported one."})]})}}DeprecatedStandinEditor.widgetName="deprecated-standin";
1558
+ class DeprecatedStandinEditor extends React.Component{serialize(){return EditorJsonify.serialize.call(this)}render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("p",{children:"This widget has been deprecated and removed"}),jsxRuntimeExports.jsx("p",{children:"Learners will see a message and they will not be graded on this part. Please replace this widget with a supported one."})]})}}
1558
1559
 
1559
- class DropdownEditor extends React.Component{render(){const dropdownGroupName=_.uniqueId("perseus_dropdown_");const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-dropdown",children:[jsxRuntimeExports.jsxs("div",{className:"dropdown-info",children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:"Dropdown"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["The drop down is useful for making inequalities in a custom format. We normally use the symbols ","<",","," ",">",', ≤, ≥ (in that order) which you can copy into the choices. When possible, use the "multiple choice" answer type instead.']})})]}),jsxRuntimeExports.jsxs("div",{className:"dropdown-field",children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",children:["Visible label",jsxRuntimeExports.jsx(TextField,{value:this.props.visibleLabel,onChange:this.onVisibleLabelChange})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Optional visible label"})})]}),jsxRuntimeExports.jsxs("div",{className:"dropdown-field",children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",children:["Aria label",jsxRuntimeExports.jsx(TextField,{value:this.props.ariaLabel,onChange:this.onAriaLabelChange,type:"text"})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{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 writing 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."})," ",'If left blank, the value will default to "Select an answer".']})})]}),jsxRuntimeExports.jsxs("div",{className:"dropdown-field",children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",children:["Placeholder",jsxRuntimeExports.jsx(TextField,{value:this.props.placeholder,onChange:this.onPlaceholderChange,placeholder:"Placeholder value"})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"This value will appear as the drop down default. It should give the user some indication of the values available in the drop down itself, e.g., Yes/No/Maybe."})})]}),jsxRuntimeExports.jsx("div",{className:"clearfix"}),jsxRuntimeExports.jsx(BodyText,{children:"Choices"}),jsxRuntimeExports.jsx("ul",{className:"dropdown-choices",children:this.props.choices.map((choice,i)=>{const choiceBackgroundColor=choice.correct?semanticColor.core.background.success.subtle:semanticColor.core.background.critical.subtle;return jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("div",{className:"dropdown-choice",children:[jsxRuntimeExports.jsx("input",{type:"radio",ref:"radio"+i,name:dropdownGroupName,checked:choice.correct,onChange:()=>this.onCorrectChange(i)}),jsxRuntimeExports.jsx(TextField,{value:choice.content,ref:"editor"+i,"aria-label":`Choice ${i+1} content`,disabled:editingDisabled,style:{backgroundColor:choiceBackgroundColor},onChange:newContent=>this.onContentChange(i,newContent)}),jsxRuntimeExports.jsx(IconButton,{icon:trashIcon,"aria-label":"Delete choice",disabled:editingDisabled,kind:"tertiary",size:"small",onClick:()=>this.removeChoice(i)})]})},""+i)},this)}),jsxRuntimeExports.jsx("div",{className:"add-choice-container",children:jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:editingDisabled,onClick:this.addChoice,startIcon:plusIcon,children:"Add a choice"})})]})}constructor(...args){super(...args),this.onVisibleLabelChange=visibleLabel=>{this.props.onChange({visibleLabel});},this.onAriaLabelChange=ariaLabel=>{this.props.onChange({ariaLabel});},this.onPlaceholderChange=placeholder=>{this.props.onChange({placeholder});},this.onCorrectChange=choiceIndex=>{const choices=this.props.choices.map(function(choice,i){return _.extend({},choice,{correct:i===choiceIndex})});this.props.onChange({choices:choices});},this.onContentChange=(choiceIndex,newContent)=>{const choices=this.props.choices.slice();const choice=_.clone(choices[choiceIndex]);choice.content=newContent;choices[choiceIndex]=choice;this.props.onChange({choices:choices});},this.addChoice=()=>{const choices=this.props.choices;const blankChoice={content:"",correct:false};this.props.onChange({choices:choices.concat([blankChoice])},this.focus.bind(this,choices.length));},this.removeChoice=choiceIndex=>{const choices=_(this.props.choices).clone();choices.splice(choiceIndex,1);this.props.onChange({choices:choices});},this.focus=i=>{ReactDOM.findDOMNode(this.refs["editor"+i]).focus();return true},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}DropdownEditor.propTypes={choices:PropTypes.arrayOf(PropTypes.shape({content:PropTypes.string,correct:PropTypes.bool})),placeholder:PropTypes.string};DropdownEditor.widgetName="dropdown";DropdownEditor.defaultProps=dropdownLogic.defaultWidgetOptions;
1560
+ class DropdownEditor extends React.Component{render(){const dropdownGroupName=_.uniqueId("perseus_dropdown_");const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-dropdown",children:[jsxRuntimeExports.jsxs("div",{className:"dropdown-info",children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:"Dropdown"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["The drop down is useful for making inequalities in a custom format. We normally use the symbols ","<",","," ",">",', ≤, ≥ (in that order) which you can copy into the choices. When possible, use the "multiple choice" answer type instead.']})})]}),jsxRuntimeExports.jsxs("div",{className:"dropdown-field",children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",children:["Visible label",jsxRuntimeExports.jsx(TextField,{value:this.props.visibleLabel,onChange:this.onVisibleLabelChange})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Optional visible label"})})]}),jsxRuntimeExports.jsxs("div",{className:"dropdown-field",children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",children:["Aria label",jsxRuntimeExports.jsx(TextField,{value:this.props.ariaLabel,onChange:this.onAriaLabelChange,type:"text"})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{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 writing 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."})," ",'If left blank, the value will default to "Select an answer".']})})]}),jsxRuntimeExports.jsxs("div",{className:"dropdown-field",children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",children:["Placeholder",jsxRuntimeExports.jsx(TextField,{value:this.props.placeholder,onChange:this.onPlaceholderChange,placeholder:"Placeholder value"})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"This value will appear as the drop down default. It should give the user some indication of the values available in the drop down itself, e.g., Yes/No/Maybe."})})]}),jsxRuntimeExports.jsx("div",{className:"clearfix"}),jsxRuntimeExports.jsx(BodyText,{children:"Choices"}),jsxRuntimeExports.jsx("ul",{className:"dropdown-choices",children:this.props.choices.map((choice,i)=>{const choiceBackgroundColor=choice.correct?semanticColor.core.background.success.subtle:semanticColor.core.background.critical.subtle;return jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsxs("div",{className:"dropdown-choice",children:[jsxRuntimeExports.jsx("input",{type:"radio",ref:"radio"+i,name:dropdownGroupName,checked:choice.correct,onChange:()=>this.onCorrectChange(i)}),jsxRuntimeExports.jsx(TextField,{value:choice.content,ref:"editor"+i,"aria-label":`Choice ${i+1} content`,disabled:editingDisabled,style:{backgroundColor:choiceBackgroundColor},onChange:newContent=>this.onContentChange(i,newContent)}),jsxRuntimeExports.jsx(IconButton,{icon:trashIcon,"aria-label":"Delete choice",disabled:editingDisabled,kind:"tertiary",size:"small",onClick:()=>this.removeChoice(i)})]})},""+i)},this)}),jsxRuntimeExports.jsx("div",{className:"add-choice-container",children:jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:editingDisabled,onClick:this.addChoice,startIcon:plusIcon,children:"Add a choice"})})]})}constructor(...args){super(...args),this.onVisibleLabelChange=visibleLabel=>{this.props.onChange({visibleLabel});},this.onAriaLabelChange=ariaLabel=>{this.props.onChange({ariaLabel});},this.onPlaceholderChange=placeholder=>{this.props.onChange({placeholder});},this.onCorrectChange=choiceIndex=>{const choices=this.props.choices.map(function(choice,i){return _.extend({},choice,{correct:i===choiceIndex})});this.props.onChange({choices:choices});},this.onContentChange=(choiceIndex,newContent)=>{const choices=this.props.choices.slice();const choice=_.clone(choices[choiceIndex]);choice.content=newContent;choices[choiceIndex]=choice;this.props.onChange({choices:choices});},this.addChoice=()=>{const choices=this.props.choices;const blankChoice={content:"",correct:false};this.props.onChange({choices:choices.concat([blankChoice])},this.focus.bind(this,choices.length));},this.removeChoice=choiceIndex=>{const choices=_(this.props.choices).clone();choices.splice(choiceIndex,1);this.props.onChange({choices:choices});},this.focus=i=>{ReactDOM.findDOMNode(this.refs["editor"+i]).focus();return true},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}DropdownEditor.propTypes={choices:PropTypes.arrayOf(PropTypes.shape({content:PropTypes.string,correct:PropTypes.bool})),placeholder:PropTypes.string};DropdownEditor.defaultProps=dropdownLogic.defaultWidgetOptions;
1560
1561
 
1561
- const{TextInput: TextInput$4}=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$4,{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$4,{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,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.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}ExplanationEditor.widgetName="explanation";ExplanationEditor.defaultProps=explanationLogic.defaultWidgetOptions;
1562
+ const{TextInput: TextInput$4}=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$4,{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$4,{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,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.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}ExplanationEditor.defaultProps=explanationLogic.defaultWidgetOptions;
1562
1563
 
1563
- var styles$P = {"paddedX":"perseus_o-vx07Zg","paddedY":"perseus_873n-udD","answerOption":"perseus_x7ZKrcCV","buttonRow":"perseus_oxdBYi-q","buttonSets":"perseus_086GhAqW","answersSubtitle":"perseus_Xz7kTZ-l","answersGroup":"perseus_xzQO7ISR","answersList":"perseus_AIxq-uWT","deleteButton":"perseus_ppk4h52d"};
1564
+ var styles$O = {"paddedX":"perseus_o-vx07Zg","paddedY":"perseus_873n-udD","answerOption":"perseus_x7ZKrcCV","buttonRow":"perseus_oxdBYi-q","buttonSets":"perseus_086GhAqW","answersSubtitle":"perseus_Xz7kTZ-l","answersGroup":"perseus_xzQO7ISR","answersList":"perseus_AIxq-uWT","deleteButton":"perseus_ppk4h52d"};
1564
1565
 
1565
- const{ButtonGroup: ButtonGroup$7}=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 derivedExtraKeys=deriveExtraKeys({...restProps,answerForms});this.props.onChange({answerForms,extraKeys:derivedExtraKeys});}changeSimplify(index,simplify){const answerForm={...this.props.answerForms[index],simplify};this.updateAnswerForm(index,answerForm);}changeForm(index,form){const answerForm={...this.props.answerForms[index],form};this.updateAnswerForm(index,answerForm);}changeConsidered(index,considered){const answerForm={...this.props.answerForms[index],considered};this.updateAnswerForm(index,answerForm);}changeTimes(times){this.props.onChange({times:times});}render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;const answerOptions=this.props.answerForms.map((ans,index)=>{const expressionProps={options:{times:this.props.times,functions:this.props.functions,buttonSets:this.props.buttonSets,buttonsVisible:"focused",visibleLabel:this.props.visibleLabel,ariaLabel:this.props.ariaLabel,answerForms:this.props.answerForms},userInput:ans.value,handleUserInput:input=>this.changeExpressionWidget(index,input),trackInteraction:()=>{},widgetId:this.props.widgetId+"-"+ans.key};return jsxRuntimeExports.jsx(AnswerOption,{considered:ans.considered,editingDisabled:editingDisabled,expressionProps:expressionProps,form:ans.form,simplify:ans.simplify,onDelete:()=>this.handleRemoveForm(index),onChangeSimplify:simplify=>this.changeSimplify(index,simplify),onChangeForm:form=>this.changeForm(index,form),onChangeConsidered:considered=>this.changeConsidered(index,considered)},ans.key)});const buttonSetChoices=buttonSetsList.map(name=>{const isBasic=name==="basic";const checked=this.props.buttonSets.includes(name)||isBasic;return jsxRuntimeExports.jsx(Checkbox$1,{label:name,checked:checked,disabled:isBasic,onChange:()=>this.handleButtonSet(name)},name)});buttonSetChoices.unshift(jsxRuntimeExports.jsx(Checkbox$1,{label:"show ÷ button",checked:this.props.buttonSets.includes("basic+div"),onChange:this.handleToggleDiv},"show ÷ button"));return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Heading$1,{size:"medium",children:"Global Options"}),jsxRuntimeExports.jsx("div",{className:styles$P.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Visible label",jsxRuntimeExports.jsx(InfoTip,{children:"Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."})]}),value:this.props.visibleLabel||"",onChange:this.handleVisibleLabel})}),jsxRuntimeExports.jsx("div",{className:styles$P.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Aria label",jsxRuntimeExports.jsxs(InfoTip,{children:["Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see"," ",jsxRuntimeExports.jsx("a",{href:"https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",target:"_blank",rel:"noreferrer",children:"this article."})]})]}),value:this.props.ariaLabel||"",onChange:this.handleAriaLabel})}),jsxRuntimeExports.jsx("div",{className:styles$P.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Function variables",jsxRuntimeExports.jsx(InfoTip,{children:'Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means "f of x" and not "f times x".'})]}),value:this.state.functionsInternal,onChange:this.handleFunctions})}),jsxRuntimeExports.jsx("div",{className:styles$P.paddedY,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Use × instead of ⋅ for multiplication",jsxRuntimeExports.jsx(InfoTip,{children:"For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."})]}),checked:this.props.times,onChange:newCheckedState=>{this.changeTimes(newCheckedState);}})}),jsxRuntimeExports.jsxs("div",{className:styles$P.paddedY,children:[jsxRuntimeExports.jsx(Heading$1,{size:"small",className:styles$P.buttonSets,children:"Button Sets"}),buttonSetChoices]}),jsxRuntimeExports.jsx(Heading$1,{size:"medium",children:"Answers"}),jsxRuntimeExports.jsx(BodyText,{size:"small",className:styles$P.answersSubtitle,children:"student responses area matched against these from top to bottom"}),jsxRuntimeExports.jsxs(View,{className:styles$P.answersGroup,children:[jsxRuntimeExports.jsx(View,{className:styles$P.answersList,children:answerOptions}),jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.newAnswer,children:"Add new answer"})]})]})}constructor(props){super(props),this.getSaveWarnings=()=>{const issues=[];if(this.props.answerForms.length===0){issues.push("No answers specified");}else {const hasCorrect=this.props.answerForms.some(form=>{return form.considered==="correct"});if(!hasCorrect){issues.push("No correct answer specified");}_(this.props.answerForms).each((form,ix)=>{if(this.props.value===""){issues.push(`Answer ${ix+1} is empty`);}else {const expression=KAS.parse(form.value,{functions:this.props.functions});if(!expression.parsed){issues.push(`Couldn't parse ${form.value}`);}else if(form.simplify&&!expression.expr.isSimplified()){issues.push(`${form.value} isn't simplified, but is required" +
1566
- " to be`);}}});}return issues},this.newAnswer=()=>{const answerForms=this.props.answerForms.slice();const newKey=crypto.randomUUID();const newAnswerForm={considered:"correct",form:false,key:`${newKey}`,simplify:false,value:""};answerForms.push(newAnswerForm);this.props.onChange({answerForms});},this.handleRemoveForm=i=>{const updatedAnswerForms=this.props.answerForms.slice();updatedAnswerForms.splice(i,1);this.props.onChange({answerForms:updatedAnswerForms});},this.handleButtonSet=changingName=>{const buttonSetNames=buttonSetsList;const buttonSets=buttonSetNames.filter(set=>{return this.props.buttonSets.includes(set)!==(set===changingName)});this.props.onChange({buttonSets});},this.handleToggleDiv=()=>{let keep;let remove;if(this.props.buttonSets.includes("basic+div")){keep="basic";remove="basic+div";}else {keep="basic+div";remove="basic";}const buttonSets=this.props.buttonSets.filter(set=>set!==remove).concat(keep);this.props.onChange({buttonSets});},this.handleTexInsert=str=>{this.refs.expression.insert(str);},this.handleFunctions=value=>{this.setState({functionsInternal:value});const newProps={};newProps.functions=value.split(/[ ,]+/).filter(isTruthy);this.props.onChange(newProps);},this.handleVisibleLabel=visibleLabel=>{this.props.onChange({visibleLabel});},this.handleAriaLabel=ariaLabel=>{this.props.onChange({ariaLabel});},this.changeExpressionWidget=(index,input)=>{const answerForm={...this.props.answerForms[index],value:input};this.updateAnswerForm(index,answerForm);};this.state={functionsInternal:this.props.functions.join(" ")};}}ExpressionEditor.widgetName="expression";ExpressionEditor.defaultProps={...expressionLogic.defaultWidgetOptions};const findNextIn=function(arr,val){let ix=arr.indexOf(val);ix=(ix+1)%arr.length;return arr[ix]};class AnswerOption extends React.Component{render(){const{editingDisabled}=this.props;const removeButton=this.state.deleteFocused?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleImSure,actionType:"destructive",children:"I'm sure!"}),jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleCancelDelete,kind:"secondary",children:"Cancel"})]}):jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleDelete,actionType:"destructive",kind:"tertiary",className:styles$P.deleteButton,children:"Delete"});return jsxRuntimeExports.jsxs("div",{className:styles$P.answerOption,children:[jsxRuntimeExports.jsx(ButtonGroup$7,{onChange:this.toggleConsidered,allowEmpty:false,disabled:editingDisabled,value:this.props.considered,selectedButtonStyle:consideredButtonStyles[this.props.considered],buttons:PerseusExpressionAnswerFormConsidered.map(c=>({value:c,content:c,title:`This answer will be considered ${c}`}))}),jsxRuntimeExports.jsx(Expression,{...this.props.expressionProps}),jsxRuntimeExports.jsx("div",{className:`${styles$P.paddedY} ${styles$P.paddedX}`,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must have the same form.",jsxRuntimeExports.jsx(InfoTip,{children:"The student's answer must be in the same form. Commutativity and excess negative signs are ignored."})]}),checked:this.props.form,onChange:this.props.onChangeForm})}),jsxRuntimeExports.jsx("div",{className:`${styles$P.paddedY} ${styles$P.paddedX}`,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Answer expression must be fully expanded and simplified.",jsxRuntimeExports.jsx(InfoTip,{children:'The student\'s answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response "Your answer is not fully expanded and simplified."'})]}),checked:this.props.simplify,onChange:this.props.onChangeSimplify})}),jsxRuntimeExports.jsx("div",{className:`${styles$P.buttonRow} ${styles$P.paddedY}`,children:removeButton})]})}constructor(...args){super(...args),this.state={deleteFocused:false},this.handleImSure=()=>{this.props.onDelete();this.handleCancelDelete();},this.handleCancelDelete=()=>{this.setState({deleteFocused:false});},this.handleDelete=()=>{this.setState({deleteFocused:true});},this.toggleConsidered=()=>{const newVal=findNextIn(PerseusExpressionAnswerFormConsidered,this.props.considered);this.props.onChangeConsidered(newVal);};}}const wbStyles$1=StyleSheet.create({answerStatusWrong:{backgroundColor:semanticColor.core.background.critical.subtle},answerStatusCorrect:{backgroundColor:semanticColor.core.background.success.subtle},answerStatusUngraded:{backgroundColor:semanticColor.core.background.instructive.subtle}});const consideredButtonStyles={wrong:wbStyles$1.answerStatusWrong,correct:wbStyles$1.answerStatusCorrect,ungraded:wbStyles$1.answerStatusUngraded};
1566
+ const{ButtonGroup: ButtonGroup$7}=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 derivedExtraKeys=deriveExtraKeys({...restProps,answerForms});this.props.onChange({answerForms,extraKeys:derivedExtraKeys});}changeSimplify(index,simplify){const answerForm={...this.props.answerForms[index],simplify};this.updateAnswerForm(index,answerForm);}changeForm(index,form){const answerForm={...this.props.answerForms[index],form};this.updateAnswerForm(index,answerForm);}changeConsidered(index,considered){const answerForm={...this.props.answerForms[index],considered};this.updateAnswerForm(index,answerForm);}changeTimes(times){this.props.onChange({times:times});}render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;const answerOptions=this.props.answerForms.map((ans,index)=>{const expressionProps={options:{times:this.props.times,functions:this.props.functions,buttonSets:this.props.buttonSets,buttonsVisible:"focused",visibleLabel:this.props.visibleLabel,ariaLabel:this.props.ariaLabel,answerForms:this.props.answerForms},userInput:ans.value,handleUserInput:input=>this.changeExpressionWidget(index,input),trackInteraction:()=>{},widgetId:this.props.widgetId+"-"+ans.key};return jsxRuntimeExports.jsx(AnswerOption,{considered:ans.considered,editingDisabled:editingDisabled,expressionProps:expressionProps,form:ans.form,simplify:ans.simplify,onDelete:()=>this.handleRemoveForm(index),onChangeSimplify:simplify=>this.changeSimplify(index,simplify),onChangeForm:form=>this.changeForm(index,form),onChangeConsidered:considered=>this.changeConsidered(index,considered)},ans.key)});const buttonSetChoices=buttonSetsList.map(name=>{const isBasic=name==="basic";const checked=this.props.buttonSets.includes(name)||isBasic;return jsxRuntimeExports.jsx(Checkbox$1,{label:name,checked:checked,disabled:isBasic,onChange:()=>this.handleButtonSet(name)},name)});buttonSetChoices.unshift(jsxRuntimeExports.jsx(Checkbox$1,{label:"show ÷ button",checked:this.props.buttonSets.includes("basic+div"),onChange:this.handleToggleDiv},"show ÷ button"));return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Heading$1,{size:"medium",children:"Global Options"}),jsxRuntimeExports.jsx("div",{className:styles$O.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Visible label",jsxRuntimeExports.jsx(InfoTip,{children:"Optional visible text; strongly encouraged to help learners using dictation software, but can be omitted if the surrounding content provides enough context."})]}),value:this.props.visibleLabel||"",onChange:this.handleVisibleLabel})}),jsxRuntimeExports.jsx("div",{className:styles$O.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Aria label",jsxRuntimeExports.jsxs(InfoTip,{children:["Label text that's read by screen readers. Highly recommend adding a label here to ensure your exercise is accessible. For more information on writting accessible labels, please see"," ",jsxRuntimeExports.jsx("a",{href:"https://www.w3.org/WAI/tips/designing/#ensure-that-form-elements-include-clearly-associated-labels",target:"_blank",rel:"noreferrer",children:"this article."})]})]}),value:this.props.ariaLabel||"",onChange:this.handleAriaLabel})}),jsxRuntimeExports.jsx("div",{className:styles$O.paddedY,children:jsxRuntimeExports.jsx(LabeledTextField,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Function variables",jsxRuntimeExports.jsx(InfoTip,{children:'Single-letter variables listed here will be interpreted as functions. This let us know that f(x) means "f of x" and not "f times x".'})]}),value:this.state.functionsInternal,onChange:this.handleFunctions})}),jsxRuntimeExports.jsx("div",{className:styles$O.paddedY,children:jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:["Use × instead of ⋅ for multiplication",jsxRuntimeExports.jsx(InfoTip,{children:"For pre-algebra problems this option displays multiplication as \\times instead of \\cdot in both the rendered output and the acceptable formats examples."})]}),checked:this.props.times,onChange:newCheckedState=>{this.changeTimes(newCheckedState);}})}),jsxRuntimeExports.jsxs("div",{className:styles$O.paddedY,children:[jsxRuntimeExports.jsx(Heading$1,{size:"small",className:styles$O.buttonSets,children:"Button Sets"}),buttonSetChoices]}),jsxRuntimeExports.jsx(Heading$1,{size:"medium",children:"Answers"}),jsxRuntimeExports.jsx(BodyText,{size:"small",className:styles$O.answersSubtitle,children:"student responses area matched against these from top to bottom"}),jsxRuntimeExports.jsxs(View,{className:styles$O.answersGroup,children:[jsxRuntimeExports.jsx(View,{className:styles$O.answersList,children:answerOptions}),jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.newAnswer,children:"Add new answer"})]})]})}constructor(props){super(props),this.getSaveWarnings=()=>{const issues=[];if(this.props.answerForms.length===0){issues.push("No answers specified");}else {const hasCorrect=this.props.answerForms.some(form=>{return form.considered==="correct"});if(!hasCorrect){issues.push("No correct answer specified");}_(this.props.answerForms).each((form,ix)=>{if(this.props.value===""){issues.push(`Answer ${ix+1} is empty`);}else {const expression=KAS.parse(form.value,{functions:this.props.functions});if(!expression.parsed){issues.push(`Couldn't parse ${form.value}`);}else if(form.simplify&&!expression.expr.isSimplified()){issues.push(`${form.value} isn't simplified, but is required" +
1567
+ " 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.defaultProps={...expressionLogic.defaultWidgetOptions};const findNextIn=function(arr,val){let ix=arr.indexOf(val);ix=(ix+1)%arr.length;return arr[ix]};class AnswerOption extends React.Component{render(){const{editingDisabled}=this.props;const removeButton=this.state.deleteFocused?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleImSure,actionType:"destructive",children:"I'm sure!"}),jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleCancelDelete,kind:"secondary",children:"Cancel"})]}):jsxRuntimeExports.jsx(Button,{size:"small",disabled:editingDisabled,onClick:this.handleDelete,actionType:"destructive",kind:"tertiary",className:styles$O.deleteButton,children:"Delete"});return jsxRuntimeExports.jsxs("div",{className:styles$O.answerOption,children:[jsxRuntimeExports.jsx(ButtonGroup$7,{onChange:this.toggleConsidered,allowEmpty:false,disabled:editingDisabled,value:this.props.considered,selectedButtonStyle:consideredButtonStyles[this.props.considered],buttons:PerseusExpressionAnswerFormConsidered.map(c=>({value:c,content:c,title:`This answer will be considered ${c}`}))}),jsxRuntimeExports.jsx(Expression,{...this.props.expressionProps}),jsxRuntimeExports.jsx("div",{className:`${styles$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,{children:"The student's answer must be in the same form. Commutativity and excess negative signs are ignored."})]}),checked:this.props.form,onChange:this.props.onChangeForm})}),jsxRuntimeExports.jsx("div",{className:`${styles$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,{children:'The student\'s answer must be fully expanded and simplified. Answering this equation (x^2+2x+1) with this factored equation (x+1)^2 will render this response "Your answer is not fully expanded and simplified."'})]}),checked:this.props.simplify,onChange:this.props.onChangeSimplify})}),jsxRuntimeExports.jsx("div",{className:`${styles$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 wbStyles$1=StyleSheet.create({answerStatusWrong:{backgroundColor:semanticColor.core.background.critical.subtle},answerStatusCorrect:{backgroundColor:semanticColor.core.background.success.subtle},answerStatusUngraded:{backgroundColor:semanticColor.core.background.instructive.subtle}});const consideredButtonStyles={wrong:wbStyles$1.answerStatusWrong,correct:wbStyles$1.answerStatusCorrect,ungraded:wbStyles$1.answerStatusUngraded};
1567
1568
 
1568
- class FreeResponseEditor extends React.Component{render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Question",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.question,onChange:newValue=>this.props.onChange({question:newValue})}),styles:{root:styles$O.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Placeholder",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.placeholder,onChange:newValue=>this.props.onChange({placeholder:newValue})}),styles:{root:styles$O.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Allow unlimited characters",field:jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.allowUnlimitedCharacters,onChange:val=>this.props.onChange({allowUnlimitedCharacters:val})}),styles:{root:styles$O.labeledInputField}}),!this.props.allowUnlimitedCharacters&&jsxRuntimeExports.jsx(LabeledField,{label:"Character limit",field:jsxRuntimeExports.jsx(TextField,{type:"number",min:1,value:String(this.props.characterLimit),onChange:this.handleUpdateCharacterLimit}),styles:{root:styles$O.labeledInputField}}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs(View,{style:styles$O.criteriaList,tag:"fieldset",children:[jsxRuntimeExports.jsx(BodyText,{tag:"legend",children:"Scoring criteria"}),this.renderCriteriaList(editingDisabled)]}),jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsx(Button,{onClick:this.handleAddCriterion,startIcon:plusCircle,disabled:editingDisabled,children:"Add an item"})})]})]})}constructor(...args){super(...args),this.serialize=()=>{return {allowUnlimitedCharacters:this.props.allowUnlimitedCharacters,characterLimit:this.props.characterLimit,placeholder:this.props.placeholder,question:this.props.question,scoringCriteria:this.props.scoringCriteria}},this.getSaveWarnings=()=>{const warnings=[];if(!this.props.question){warnings.push("The question is empty");}if(this.props.question.match(Util.rWidgetRule)!=null){warnings.push("The question contains a widget");}return warnings},this.handleUpdateCharacterLimit=newValue=>{const val=parseInt(newValue);if(isNaN(val)){return}this.props.onChange({characterLimit:Math.max(1,val)});},this.handleUpdateCriterion=(index,criterion)=>{const newCriteria=this.props.scoringCriteria.map((c,i)=>{if(i===index){return criterion}return c});this.props.onChange({scoringCriteria:newCriteria});},this.handleDeleteCriterion=index=>{this.props.onChange({scoringCriteria:this.props.scoringCriteria.filter((_,i)=>i!==index)});},this.handleAddCriterion=()=>{this.props.onChange({scoringCriteria:[...this.props.scoringCriteria,{text:""}]});},this.renderCriteriaList=editingDisabled=>{const isDeletable=this.props.scoringCriteria.length>1;return this.props.scoringCriteria.map((criterion,index)=>{return jsxRuntimeExports.jsx(CriterionEditor,{criterion:criterion,index:index,isDeletable:isDeletable,editingDisabled:editingDisabled,onChange:this.handleUpdateCriterion,onDelete:this.handleDeleteCriterion},index)})};}}FreeResponseEditor.defaultProps={...freeResponseLogic.defaultWidgetOptions};FreeResponseEditor.widgetName="free-response";const CriterionEditor=function(props){return jsxRuntimeExports.jsxs(View,{style:styles$O.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$O.deleteButtonContainer,children:jsxRuntimeExports.jsx(Button,{"aria-label":`Delete criterion ${props.index+1}`,actionType:"destructive",disabled:!props.isDeletable||props.editingDisabled,kind:"tertiary",onClick:()=>props.onDelete(props.index),size:"small",startIcon:trashIcon$1,children:"Delete"})})]})};const styles$O=StyleSheet.create({criteriaList:{gap:spacing.small_12},criterionContainer:{paddingBlockStart:spacing.xSmall_8,paddingBlockEnd:spacing.xSmall_8,borderBlockEnd:`1px solid ${semanticColor.core.border.neutral.subtle}`,":last-child":{borderBlockEnd:"none"}},deleteButtonContainer:{display:"flex",flexDirection:"row",justifyContent:"flex-end"},labeledInputField:{paddingBlockEnd:spacing.large_24}});
1569
+ class FreeResponseEditor extends React.Component{render(){const editingDisabled=this.props.apiOptions.editingDisabled??false;return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Question",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.question,onChange:newValue=>this.props.onChange({question:newValue})}),styles:{root:styles$N.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Placeholder",field:jsxRuntimeExports.jsx(TextArea,{value:this.props.placeholder,onChange:newValue=>this.props.onChange({placeholder:newValue})}),styles:{root:styles$N.labeledInputField}}),jsxRuntimeExports.jsx(LabeledField,{label:"Allow unlimited characters",field:jsxRuntimeExports.jsx(Checkbox$1,{checked:this.props.allowUnlimitedCharacters,onChange:val=>this.props.onChange({allowUnlimitedCharacters:val})}),styles:{root:styles$N.labeledInputField}}),!this.props.allowUnlimitedCharacters&&jsxRuntimeExports.jsx(LabeledField,{label:"Character limit",field:jsxRuntimeExports.jsx(TextField,{type:"number",min:1,value:String(this.props.characterLimit),onChange:this.handleUpdateCharacterLimit}),styles:{root:styles$N.labeledInputField}}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs(View,{style:styles$N.criteriaList,tag:"fieldset",children:[jsxRuntimeExports.jsx(BodyText,{tag:"legend",children:"Scoring criteria"}),this.renderCriteriaList(editingDisabled)]}),jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsx(Button,{onClick:this.handleAddCriterion,startIcon:plusCircle,disabled:editingDisabled,children:"Add an item"})})]})]})}constructor(...args){super(...args),this.serialize=()=>{return {allowUnlimitedCharacters:this.props.allowUnlimitedCharacters,characterLimit:this.props.characterLimit,placeholder:this.props.placeholder,question:this.props.question,scoringCriteria:this.props.scoringCriteria}},this.getSaveWarnings=()=>{const warnings=[];if(!this.props.question){warnings.push("The question is empty");}if(this.props.question.match(Util.rWidgetRule)!=null){warnings.push("The question contains a widget");}return warnings},this.handleUpdateCharacterLimit=newValue=>{const val=parseInt(newValue);if(isNaN(val)){return}this.props.onChange({characterLimit:Math.max(1,val)});},this.handleUpdateCriterion=(index,criterion)=>{const newCriteria=this.props.scoringCriteria.map((c,i)=>{if(i===index){return criterion}return c});this.props.onChange({scoringCriteria:newCriteria});},this.handleDeleteCriterion=index=>{this.props.onChange({scoringCriteria:this.props.scoringCriteria.filter((_,i)=>i!==index)});},this.handleAddCriterion=()=>{this.props.onChange({scoringCriteria:[...this.props.scoringCriteria,{text:""}]});},this.renderCriteriaList=editingDisabled=>{const isDeletable=this.props.scoringCriteria.length>1;return this.props.scoringCriteria.map((criterion,index)=>{return jsxRuntimeExports.jsx(CriterionEditor,{criterion:criterion,index:index,isDeletable:isDeletable,editingDisabled:editingDisabled,onChange:this.handleUpdateCriterion,onDelete:this.handleDeleteCriterion},index)})};}}FreeResponseEditor.defaultProps={...freeResponseLogic.defaultWidgetOptions};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||props.editingDisabled,kind:"tertiary",onClick:()=>props.onDelete(props.index),size:"small",startIcon:trashIcon$1,children:"Delete"})})]})};const styles$N=StyleSheet.create({criteriaList:{gap:spacing.small_12},criterionContainer:{paddingBlockStart:spacing.xSmall_8,paddingBlockEnd:spacing.xSmall_8,borderBlockEnd:`1px solid ${semanticColor.core.border.neutral.subtle}`,":last-child":{borderBlockEnd:"none"}},deleteButtonContainer:{display:"flex",flexDirection:"row",justifyContent:"flex-end"},labeledInputField:{paddingBlockEnd:spacing.large_24}});
1569
1570
 
1570
- var styles$N = {"title":"perseus_n2P9eL87","input":"perseus_09NCEMrz","hintsTitle":"perseus_fGIysYAE"};
1571
+ var styles$M = {"title":"perseus_n2P9eL87","input":"perseus_09NCEMrz","hintsTitle":"perseus_fGIysYAE"};
1571
1572
 
1572
- const{TextInput: TextInput$3}=components;class GradedGroupEditor extends React.Component{render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{className:styles$N.title,children:["Title:"," ",jsxRuntimeExports.jsx(TextInput$3,{value:this.props.title,className:styles$N.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,onChange:this.props.onChange,warnNoPrompt:true,warnNoWidgets:true}),!this.props.hint&&jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,size:"small",kind:"tertiary",onClick:this.handleAddHint,disabled:editingDisabled,children:"Add a hint"}),this.props.hint&&jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor",children:[jsxRuntimeExports.jsx("div",{className:styles$N.hintsTitle,children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.hintEditor,content:this.props.hint.content,widgets:this.props.hint.widgets,apiOptions:this.props.apiOptions,images:this.props.hint.images,widgetEnabled:true,onChange:props=>{this.change("hint",Object.assign({},this.props.hint,props));}}),jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,size:"small",kind:"tertiary",onClick:this.handleRemoveHint,disabled:editingDisabled,style:{marginInlineStart:"auto",display:"flex"},children:"Remove this hint"})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.hintEditor=React.createRef(),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handleAddHint=()=>{const hint={content:"",images:{},widgets:{}};this.props.onChange({hint},()=>{this.hintEditor.current?.focus();});},this.handleRemoveHint=()=>{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.widgetName="graded-group";GradedGroupEditor.defaultProps=gradedGroupLogic.defaultWidgetOptions;
1573
+ const{TextInput: TextInput$3}=components;class GradedGroupEditor extends React.Component{render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{className:styles$M.title,children:["Title:"," ",jsxRuntimeExports.jsx(TextInput$3,{value:this.props.title,className: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,onChange:this.props.onChange,warnNoPrompt:true,warnNoWidgets:true}),!this.props.hint&&jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,size:"small",kind:"tertiary",onClick:this.handleAddHint,disabled:editingDisabled,children:"Add a hint"}),this.props.hint&&jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor",children:[jsxRuntimeExports.jsx("div",{className:styles$M.hintsTitle,children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.hintEditor,content:this.props.hint.content,widgets:this.props.hint.widgets,apiOptions:this.props.apiOptions,images:this.props.hint.images,widgetEnabled:true,onChange:props=>{this.change("hint",Object.assign({},this.props.hint,props));}}),jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,size:"small",kind:"tertiary",onClick:this.handleRemoveHint,disabled:editingDisabled,style:{marginInlineStart:"auto",display:"flex"},children:"Remove this hint"})]}),jsxRuntimeExports.jsx(ExtrasEditor,{...this.props.answerArea??getDefaultAnswerArea(),apiOptions:this.props.apiOptions,editingDisabled:editingDisabled,onChange:changes=>{this.props.onChange({answerArea:{...getDefaultAnswerArea(),...this.props.answerArea,...changes}});}})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.hintEditor=React.createRef(),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handleAddHint=()=>{const hint={content:"",images:{},widgets:{}};this.props.onChange({hint},()=>{this.hintEditor.current?.focus();});},this.handleRemoveHint=()=>{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(),...this.props.answerArea?{answerArea:this.props.answerArea}:{}}};}}GradedGroupEditor.defaultProps=gradedGroupLogic.defaultWidgetOptions;
1573
1574
 
1574
- class GradedGroupSetEditor extends React.Component{UNSAFE_componentWillMount(){this._editors=[];}render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[this.renderGroups(),jsxRuntimeExports.jsx("button",{onClick:this.addGroup,disabled:editingDisabled,children:"Add group"})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.getSaveWarnings=()=>{return [].concat(...this._editors.map(editor=>editor?editor.getSaveWarnings():[]))},this.serialize=()=>{return {gradedGroups:this.props.gradedGroups}},this.renderGroups=()=>{const gradedGroups=this.props.gradedGroups??[];return gradedGroups.map((group,i)=>jsxRuntimeExports.jsx(GradedGroupEditor,{ref:el=>this._editors[i]=el,...group,apiOptions:this.props.apiOptions,onChange:data=>this.change("gradedGroups",setArrayItem(gradedGroups,i,{...gradedGroups[i],...data}))},i))},this.addGroup=()=>{const groups=this.props.gradedGroups??[];this.change("gradedGroups",groups.concat([GradedGroupEditor.defaultProps]));};}}GradedGroupSetEditor.widgetName="graded-group-set";GradedGroupSetEditor.defaultProps=gradedGroupSetLogic.defaultWidgetOptions;const setArrayItem=(list,i,value)=>[...list.slice(0,i),value,...list.slice(i+1)];
1575
+ class GradedGroupSetEditor extends React.Component{UNSAFE_componentWillMount(){this._editors=[];}render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-group-editor",children:[this.renderGroups(),jsxRuntimeExports.jsx("button",{onClick:this.addGroup,disabled:editingDisabled,children:"Add group"})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.getSaveWarnings=()=>{return [].concat(...this._editors.map(editor=>editor?editor.getSaveWarnings():[]))},this.serialize=()=>{return {gradedGroups:this.props.gradedGroups}},this.renderGroups=()=>{const gradedGroups=this.props.gradedGroups??[];return gradedGroups.map((group,i)=>jsxRuntimeExports.jsx(GradedGroupEditor,{ref:el=>this._editors[i]=el,...group,apiOptions:this.props.apiOptions,onChange:data=>this.change("gradedGroups",setArrayItem(gradedGroups,i,{...gradedGroups[i],...data}))},i))},this.addGroup=()=>{const groups=this.props.gradedGroups??[];this.change("gradedGroups",groups.concat([GradedGroupEditor.defaultProps]));};}}GradedGroupSetEditor.defaultProps=gradedGroupSetLogic.defaultWidgetOptions;const setArrayItem=(list,i,value)=>[...list.slice(0,i),value,...list.slice(i+1)];
1575
1576
 
1576
1577
  const{ButtonGroup: ButtonGroup$6,RangeInput: RangeInput$5}=components;const defaultBackgroundImage$1={url:null,width:0,height:0};function numSteps$1(range,step){return Math.floor((range[1]-range[0])/step)}class GraphSettings extends React.Component{getInitialState(){return this.stateFromProps(this.props)}componentDidMount(){this._isMounted=true;this.changeGraph=_.debounce(this.changeGraph,300);}UNSAFE_componentWillReceiveProps(nextProps){if(!_.isEqual(this.props.labels,nextProps.labels)||!_.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(this.stateFromProps(nextProps));}}componentWillUnmount(){this._isMounted=false;}stateFromProps(props){return {labelsTextbox:props.labels,gridStepTextbox:props.gridStep,snapStepTextbox:props.snapStep,stepTextbox:props.step,rangeTextbox:props.range,backgroundImage:_.clone(props.backgroundImage)}}changeRulerLabel(e){this.props.onChange({rulerLabel:e.target.value});}changeRulerTicks(e){this.props.onChange({rulerTicks:+e.target.value});}changeBackgroundUrl(e){if(e.type==="keypress"&&"key"in e&&e.key!=="Enter"){return}const setUrl=(url,width,height)=>{const image=_.clone(this.props.backgroundImage);image.url=url;image.width=width;image.height=height;this.setState({backgroundImage:image},this.changeGraph);};const url=ReactDOM.findDOMNode(this.refs["bg-url"]).value;if(url){Util.getImageSize(url,(width,height)=>{if(this._isMounted){setUrl(url,width,height);}});}else {setUrl(null,0,0);}}renderLabelChoices(choices){return choices.map(function([name,value]){return jsxRuntimeExports.jsx("option",{value:value,children:name},value)})}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}validateStepValue(settings){const{step,range,name,minTicks,maxTicks}=settings;if(!_.isFinite(step)){return name+" must be a valid number"}const nSteps=numSteps$1(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}validSnapStep(step,range){return this.validateStepValue({step:step,range:range,name:"Snap step",minTicks:5,maxTicks:60})}validGridStep(step,range){return this.validateStepValue({step:step,range:range,name:"Grid step",minTicks:3,maxTicks:60})}validStep(step,range){return this.validateStepValue({step:step,range:range,name:"Step",minTicks:3,maxTicks:20})}validBackgroundImageSize(image){if(!image.url){return true}const validSize=(image.width??0)<=450&&(image.height??0)<=450;if(!validSize){return "Image must be smaller than 450px x 450px."}return true}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}changeLabel(i,e){const val=e.target.value;const labels=this.state.labelsTextbox.slice();labels[i]=val;this.setState({labelsTextbox:labels},this.changeGraph);}changeRange(i,values){const ranges=this.state.rangeTextbox.slice();ranges[i]=values;const step=this.state.stepTextbox.slice();const gridStep=this.state.gridStepTextbox.slice();const snapStep=this.state.snapStepTextbox.slice();const scale=Util.scaleFromExtent(ranges[i],this.props.box[i]);if(this.validRange(ranges[i])===true){step[i]=Util.tickStepFromExtent(ranges[i],this.props.box[i]);gridStep[i]=Util.gridStepFromTickStep(step[i],scale);snapStep[i]=gridStep[i]/2;}this.setState({stepTextbox:step,gridStepTextbox:gridStep,snapStepTextbox:snapStep,rangeTextbox:ranges},this.changeGraph);}changeStep(step){this.setState({stepTextbox:step},this.changeGraph);}changeSnapStep(snapStep){this.setState({snapStepTextbox:snapStep},this.changeGraph);}changeGridStep(gridStep){this.setState({gridStepTextbox:gridStep,snapStepTextbox:gridStep.map(function(step){return step/2})},this.changeGraph);}changeGraph(){const labels=this.state.labelsTextbox;const range=this.state.rangeTextbox.map(range=>range.map(Number));const step=this.state.stepTextbox.map(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.props.onChange({valid:true,labels:labels,range:range,step:step,gridStep:gridStep,snapStep:snapStep,backgroundImage:image});}else {this.props.onChange({valid:validationResult});}}render(){const scale=[KhanMath.roundTo(2,Util.scaleFromExtent(this.props.range[0],this.props.box[0])),KhanMath.roundTo(2,Util.scaleFromExtent(this.props.range[1],this.props.box[1]))];const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{children:[this.props.editableSettings.includes("canvas")&&jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("label",{htmlFor:"canvas-size",children:"Canvas size (x,y pixels)"}),jsxRuntimeExports.jsx(RangeInput$5,{id:"canvas-size",value:this.props.box,onChange:box=>{this.props.onChange({box:box});}})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Scale (px per div):"," ",jsxRuntimeExports.jsx(TeX,{children:"("+scale[0]+", "+scale[1]+")"})]})]}),this.props.editableSettings.includes("graph")&&jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"labels-x",children:"x Label"}),jsxRuntimeExports.jsx("input",{id:"labels-x",type:"text",className:"graph-settings-axis-label",ref:"labels-0",onChange:e=>this.changeLabel(0,e),value:this.state.labelsTextbox[0]||""})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-right-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"labels-y",children:"y Label"}),jsxRuntimeExports.jsx("input",{id:"labels-y",type:"text",className:"graph-settings-axis-label",ref:"labels-1",onChange:e=>this.changeLabel(1,e),value:this.state.labelsTextbox[1]||""})]})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"range-x",children:"x Range"}),jsxRuntimeExports.jsx(RangeInput$5,{id:"range-x",value:this.state.rangeTextbox[0],onChange:vals=>this.changeRange(0,vals)})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-right-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"range-y",children:"y Range"}),jsxRuntimeExports.jsx(RangeInput$5,{id:"range-y",value:this.state.rangeTextbox[1],onChange:vals=>this.changeRange(1,vals)})]})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"tick-step",children:"Tick Step"}),jsxRuntimeExports.jsx(RangeInput$5,{id:"tick-step",value:this.state.stepTextbox,onChange:this.changeStep})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-right-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"grid-step",children:"Grid Step"}),jsxRuntimeExports.jsx(RangeInput$5,{id:"grid-step",value:this.state.gridStepTextbox,onChange:this.changeGridStep})]})]}),this.props.editableSettings.includes("snap")&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:[jsxRuntimeExports.jsx("label",{htmlFor:"snap-step",children:"Snap Step"}),jsxRuntimeExports.jsx(RangeInput$5,{id:"snap-step",value:this.state.snapStepTextbox,onChange:this.changeSnapStep})]})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("label",{children:"Markings: "}),jsxRuntimeExports.jsx(ButtonGroup$6,{value:this.props.markings,allowEmpty:false,buttons:[{value:"graph",content:"Graph"},{value:"grid",content:"Grid"},{value:"none",content:"None"}],onChange:value=>this.props.onChange({markings:value})})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tooltips",checked:this.props.showTooltips,onChange:value=>{this.props.onChange({showTooltips:value});}})})]}),this.props.editableSettings.includes("image")&&jsxRuntimeExports.jsxs("div",{className:"image-settings",children:[jsxRuntimeExports.jsx("div",{children:"Background image:"}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("label",{htmlFor:"bg-url",children:"Url:"}),jsxRuntimeExports.jsx("input",{id:"bg-url",type:"text",className:"graph-settings-background-url",ref:"bg-url",value:this.state.backgroundImage.url||"",onChange:e=>{const image=_.clone(this.props.backgroundImage);image.url=e.target.value;this.setState({backgroundImage:image});},onKeyPress:this.changeBackgroundUrl,onBlur:this.changeBackgroundUrl}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]})]}),this.props.editableSettings.includes("measure")&&jsxRuntimeExports.jsxs("div",{className:"misc-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show ruler",checked:this.props.showRuler,onChange:value=>{this.props.onChange({showRuler:value});}})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.props.onChange({showProtractor:value});}})})]}),this.props.showRuler&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:[" ","Ruler label:"," ",jsxRuntimeExports.jsxs("select",{onChange:this.changeRulerLabel,value:this.props.rulerLabel,children:[jsxRuntimeExports.jsx("option",{value:"",children:"None"}),jsxRuntimeExports.jsx("optgroup",{label:"Metric",children:this.renderLabelChoices([["milimeters","mm"],["centimeters","cm"],["meters","m"],["kilometers","km"]])}),jsxRuntimeExports.jsx("optgroup",{label:"Imperial",children:this.renderLabelChoices([["inches","in"],["feet","ft"],["yards","yd"],["miles","mi"]])})]})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:[" ","Ruler ticks:"," ",jsxRuntimeExports.jsx("select",{onChange:this.changeRulerTicks,value:this.props.rulerTicks,children:[1,2,4,8,10,16].map(function(n){return jsxRuntimeExports.jsx("option",{value:n,children:n},n)})})]})})]})]})]})}constructor(props){super(props),this._isMounted=false;this.state=this.getInitialState();this.changeBackgroundUrl=this.changeBackgroundUrl.bind(this);this.changeGraph=this.changeGraph.bind(this);this.changeGridStep=this.changeGridStep.bind(this);this.changeLabel=this.changeLabel.bind(this);this.changeRange=this.changeRange.bind(this);this.changeRulerLabel=this.changeRulerLabel.bind(this);this.changeRulerTicks=this.changeRulerTicks.bind(this);this.changeSnapStep=this.changeSnapStep.bind(this);this.changeStep=this.changeStep.bind(this);}}GraphSettings.defaultProps={editableSettings:["graph","snap","image","measure"],box:[interactiveSizes.defaultBoxSizeSmall,interactiveSizes.defaultBoxSizeSmall],labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],gridStep:[1,1],snapStep:[1,1],valid:true,backgroundImage:defaultBackgroundImage$1,markings:"graph",rulerLabel:"",rulerTicks:10,showProtractor:false,showRuler:false,showTooltips:false};
1577
1578
 
1578
- const{MultiButtonGroup}=components;const Grapher=GrapherWidget.widget;const{chooseType,defaultPlotProps,getEquationString,typeToButton}=GrapherUtil;class GrapherEditor extends React.Component{render(){const sizeClass=containerSizeClass.SMALL;let equationString;let graph;if(this.props.graph.valid===true){const graphProps={apiOptions:this.props.apiOptions,containerSizeClass:sizeClass,options:{graph:this.props.graph,correct:this.props.correct,availableTypes:[...this.props.availableTypes]},userInput:this.props.correct,handleUserInput:userInput=>{let correct=this.props.correct;if(correct.type===userInput?.type){correct=_.extend({},correct,userInput);}else {correct=userInput;}this.props.onChange({correct:correct});},trackInteraction:function(){},static:this.props.apiOptions.editingDisabled};graph=jsxRuntimeExports.jsx(Grapher,{...graphProps});equationString=getEquationString(graphProps.userInput);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.graph.valid});}return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{children:["Correct answer"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."})})," ",": ",equationString]}),jsxRuntimeExports.jsx(GraphSettings,{editableSettings:["graph","snap","image"],box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.graph.range,labels:this.props.graph.labels,step:this.props.graph.step,gridStep:this.props.graph.gridStep,snapStep:this.props.graph.snapStep,valid:this.props.graph.valid===true,backgroundImage:this.props.graph.backgroundImage,markings:this.props.graph.markings,rulerLabel:this.props.graph.rulerLabel,rulerTicks:this.props.graph.rulerTicks,showTooltips:this.props.graph.showTooltips,onChange:newProps=>this.props.onChange({graph:{...this.props.graph,...newProps}})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("label",{children:"Available functions: "}),jsxRuntimeExports.jsx(MultiButtonGroup,{allowEmpty:false,values:this.props.availableTypes,buttons:GrapherUtil$1.allTypes.map(typeToButton),onChange:this.handleAvailableTypesChange})]}),graph]})}constructor(...args){super(...args),this.handleAvailableTypesChange=newAvailableTypes=>{let correct=this.props.correct;if(!newAvailableTypes.includes(this.props.correct.type)){const graph=this.props.graph;const newType=chooseType(newAvailableTypes);correct=defaultPlotProps(newType,graph);}this.props.onChange({availableTypes:newAvailableTypes,correct:correct});},this.serialize=()=>{return _.chain(this.props).pick("correct","availableTypes").extend({graph:_.omit(this.props.graph,"box")}).value()};}}GrapherEditor.widgetName="grapher";GrapherEditor.defaultProps=grapherLogic.defaultWidgetOptions;
1579
+ const{MultiButtonGroup}=components;const Grapher=GrapherWidget.widget;const{chooseType,defaultPlotProps,getEquationString,typeToButton}=GrapherUtil;class GrapherEditor extends React.Component{render(){const sizeClass=containerSizeClass.SMALL;let equationString;let graph;if(this.props.graph.valid===true){const graphProps={apiOptions:this.props.apiOptions,containerSizeClass:sizeClass,options:{graph:this.props.graph,correct:this.props.correct,availableTypes:[...this.props.availableTypes]},userInput:this.props.correct,handleUserInput:userInput=>{let correct=this.props.correct;if(correct.type===userInput?.type){correct=_.extend({},correct,userInput);}else {correct=userInput;}this.props.onChange({correct:correct});},trackInteraction:function(){},static:this.props.apiOptions.editingDisabled};graph=jsxRuntimeExports.jsx(Grapher,{...graphProps});equationString=getEquationString(graphProps.userInput);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.graph.valid});}return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{children:["Correct answer"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."})})," ",": ",equationString]}),jsxRuntimeExports.jsx(GraphSettings,{editableSettings:["graph","snap","image"],box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.graph.range,labels:this.props.graph.labels,step:this.props.graph.step,gridStep:this.props.graph.gridStep,snapStep:this.props.graph.snapStep,valid:this.props.graph.valid===true,backgroundImage:this.props.graph.backgroundImage,markings:this.props.graph.markings,rulerLabel:this.props.graph.rulerLabel,rulerTicks:this.props.graph.rulerTicks,showTooltips:this.props.graph.showTooltips,onChange:newProps=>this.props.onChange({graph:{...this.props.graph,...newProps}})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("label",{children:"Available functions: "}),jsxRuntimeExports.jsx(MultiButtonGroup,{allowEmpty:false,values:this.props.availableTypes,buttons:GrapherUtil$1.allTypes.map(typeToButton),onChange:this.handleAvailableTypesChange})]}),graph]})}constructor(...args){super(...args),this.handleAvailableTypesChange=newAvailableTypes=>{let correct=this.props.correct;if(!newAvailableTypes.includes(this.props.correct.type)){const graph=this.props.graph;const newType=chooseType(newAvailableTypes);correct=defaultPlotProps(newType,graph);}this.props.onChange({availableTypes:newAvailableTypes,correct:correct});},this.serialize=()=>{return _.chain(this.props).pick("correct","availableTypes").extend({graph:_.omit(this.props.graph,"box")}).value()};}}GrapherEditor.defaultProps=grapherLogic.defaultWidgetOptions;
1579
1580
 
1580
- class GroupEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize GroupEditor without Editor");return {...this.editor.current.serialize()}}render(){return jsxRuntimeExports.jsx("div",{className:"perseus-group-editor",children:jsxRuntimeExports.jsx(Editor,{ref:this.editor,content:this.props.content,widgets:this.props.widgets,apiOptions:this.props.apiOptions,images:this.props.images,widgetEnabled:true,onChange:this.props.onChange})})}constructor(...args){super(...args),this.editor=React.createRef(),this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()};}}GroupEditor.propTypes={content:PropTypes.string,widgets:PropTypes.object,images:PropTypes.object,apiOptions:ApiOptions.propTypes};GroupEditor.widgetName="group";GroupEditor.defaultProps=groupLogic.defaultWidgetOptions;
1581
+ class GroupEditor extends React.Component{serialize(){invariant(this.editor.current,"cannot serialize GroupEditor without Editor");return {...this.editor.current.serialize()}}render(){return jsxRuntimeExports.jsx("div",{className:"perseus-group-editor",children:jsxRuntimeExports.jsx(Editor,{ref:this.editor,content:this.props.content,widgets:this.props.widgets,apiOptions:this.props.apiOptions,images:this.props.images,widgetEnabled:true,onChange:this.props.onChange})})}constructor(...args){super(...args),this.editor=React.createRef(),this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()};}}GroupEditor.propTypes={content:PropTypes.string,widgets:PropTypes.object,images:PropTypes.object,apiOptions:ApiOptions.propTypes};GroupEditor.defaultProps=groupLogic.defaultWidgetOptions;
1581
1582
 
1582
- class PairEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("fieldset",{children:[jsxRuntimeExports.jsxs("label",{children:["Name:",jsxRuntimeExports.jsx(BlurInput,{value:this.props.name,onChange:this.change("name")})]}),jsxRuntimeExports.jsxs("label",{children:["Value:",jsxRuntimeExports.jsx(BlurInput,{value:this.props.value,onChange:this.change("value")})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}class PairsEditor extends React.Component{render(){const editors=this.props.pairs.map((pair,i)=>{return jsxRuntimeExports.jsx(PairEditor,{name:pair.name,value:pair.value,onChange:this.handlePairChange.bind(this,i)},i)});return jsxRuntimeExports.jsx("div",{children:editors})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handlePairChange=(pairIndex,pair)=>{const pairs=this.props.pairs.slice();pairs[pairIndex]=pair;const lastPair=pairs[pairs.length-1];if(lastPair.name&&lastPair.value){pairs.push({name:"",value:""});}this.change("pairs",pairs);};}}class IframeEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{style:{fontWeight:"bold",textAlign:"center"},children:["This widget is deprecated! ",jsxRuntimeExports.jsx("br",{}),"Try using the Video or CS Program widgets instead."]}),jsxRuntimeExports.jsxs("label",{children:["Url or Program ID:",jsxRuntimeExports.jsx(BlurInput,{value:this.props.url,onChange:this.change("url")})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Settings:",jsxRuntimeExports.jsx(PairsEditor,{pairs:this.props.settings??[],onChange:this.handleSettingsChange})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Width:",jsxRuntimeExports.jsx(BlurInput,{value:String(this.props.width),onChange:this.change("width")})]}),jsxRuntimeExports.jsxs("label",{children:["Height:",jsxRuntimeExports.jsx(BlurInput,{value:String(this.props.height),onChange:this.change("height")})]}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Allow full screen",checked:this.props.allowFullScreen,onChange:value=>{this.props.onChange({allowFullScreen:value});}}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Allow iframe content to redirect the page",checked:this.props.allowTopNavigation,onChange:value=>{this.props.onChange({allowTopNavigation:value});}})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handleSettingsChange=settings=>{this.change({settings:settings.pairs});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}IframeEditor.widgetName="iframe";IframeEditor.defaultProps=iframeLogic.defaultWidgetOptions;
1583
+ class PairEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("fieldset",{children:[jsxRuntimeExports.jsxs("label",{children:["Name:",jsxRuntimeExports.jsx(BlurInput,{value:this.props.name,onChange:this.change("name")})]}),jsxRuntimeExports.jsxs("label",{children:["Value:",jsxRuntimeExports.jsx(BlurInput,{value:this.props.value,onChange:this.change("value")})]})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}class PairsEditor extends React.Component{render(){const editors=this.props.pairs.map((pair,i)=>{return jsxRuntimeExports.jsx(PairEditor,{name:pair.name,value:pair.value,onChange:this.handlePairChange.bind(this,i)},i)});return jsxRuntimeExports.jsx("div",{children:editors})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handlePairChange=(pairIndex,pair)=>{const pairs=this.props.pairs.slice();pairs[pairIndex]=pair;const lastPair=pairs[pairs.length-1];if(lastPair.name&&lastPair.value){pairs.push({name:"",value:""});}this.change("pairs",pairs);};}}class IframeEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{style:{fontWeight:"bold",textAlign:"center"},children:["This widget is deprecated! ",jsxRuntimeExports.jsx("br",{}),"Try using the Video or CS Program widgets instead."]}),jsxRuntimeExports.jsxs("label",{children:["Url or Program ID:",jsxRuntimeExports.jsx(BlurInput,{value:this.props.url,onChange:this.change("url")})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Settings:",jsxRuntimeExports.jsx(PairsEditor,{pairs:this.props.settings??[],onChange:this.handleSettingsChange})]}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsxs("label",{children:["Width:",jsxRuntimeExports.jsx(BlurInput,{value:String(this.props.width),onChange:this.change("width")})]}),jsxRuntimeExports.jsxs("label",{children:["Height:",jsxRuntimeExports.jsx(BlurInput,{value:String(this.props.height),onChange:this.change("height")})]}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Allow full screen",checked:this.props.allowFullScreen,onChange:value=>{this.props.onChange({allowFullScreen:value});}}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx(Checkbox$1,{label:"Allow iframe content to redirect the page",checked:this.props.allowTopNavigation,onChange:value=>{this.props.onChange({allowTopNavigation:value});}})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.handleSettingsChange=settings=>{this.change({settings:settings.pairs});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}IframeEditor.defaultProps=iframeLogic.defaultWidgetOptions;
1583
1584
 
1584
1585
  const{SvgImage}=components;function ImagePreview({src,alt,width,height,wbTheme}){return jsxRuntimeExports.jsx("div",{className:"perseus-image-preview-container","data-testid":"image-preview-container","data-wb-theme":wbTheme,children:jsxRuntimeExports.jsx(SvgImage,{src:src,alt:alt,width:width,height:height,allowZoom:false})})}
1585
1586
 
1586
- var styles$M = {"dimensionsContainer":"perseus_4qo24hC2","dimensionsFieldContainer":"perseus_BMTr3h5s","xSpan":"perseus_4OCWnpA9","horizontalLine":"perseus_SKDkfpcb","altTextFieldContainer":"perseus_Uwpkz4-V"};
1587
+ var styles$L = {"dimensionsContainer":"perseus_4qo24hC2","dimensionsFieldContainer":"perseus_BMTr3h5s","xSpan":"perseus_4OCWnpA9","horizontalLine":"perseus_SKDkfpcb","altTextFieldContainer":"perseus_Uwpkz4-V"};
1587
1588
 
1588
1589
  const wbFieldStyles={root:{marginBlockEnd:sizing.size_080},label:{paddingBlockEnd:sizing.size_040}};const wbFieldStylesWithDescription={...wbFieldStyles,label:{...wbFieldStyles.label,paddingBlockEnd:0},description:{paddingBlockStart:0,paddingBlockEnd:sizing.size_040}};function isInvalidDimension(dimension){return isNaN(dimension)||dimension<=0||dimension===Infinity}
1589
1590
 
1590
- var styles$L = {"darkModeToggleContainer":"perseus_6CoX-UkT","darkModeSuppressionContainer":"perseus_fX4VwWmZ"};
1591
+ var styles$K = {"darkModeToggleContainer":"perseus_6CoX-UkT","darkModeSuppressionContainer":"perseus_fX4VwWmZ"};
1591
1592
 
1592
- function DarkModeToggle({backgroundImage,onShowToggle,onSuppressToggle,editingDisabled=false}){const[showDarkMode,setShowDarkMode]=React.useState(false);const imageUrl=(()=>{try{return new URL(backgroundImage.url??"")}catch{return null}})();const suppressFilter=imageUrl?.searchParams.has("dark-mode")??false;const toggleDarkMode=()=>{onShowToggle(showDarkMode?undefined:"syl-dark");setShowDarkMode(!showDarkMode);};const toggleSuppressFilter=()=>{onSuppressToggle({backgroundImage:{...backgroundImage,url:setDarkModeOptionInUrl(suppressFilter?undefined:"off")}});};const setDarkModeOptionInUrl=darkModeSetting=>{try{const url=new URL(backgroundImage.url??"");if(darkModeSetting==="off"){url.searchParams.append("dark-mode","off");}else {url.searchParams.delete("dark-mode");}return url.toString()}catch{return backgroundImage.url??""}};return jsxRuntimeExports.jsxs("div",{className:styles$L.darkModeToggleContainer,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Show in Dark Mode",checked:showDarkMode,disabled:editingDisabled,onChange:toggleDarkMode}),jsxRuntimeExports.jsxs("div",{className:styles$L.darkModeSuppressionContainer,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Suppress Dark Mode Filter",checked:suppressFilter,disabled:editingDisabled||!isGraphicalImage(backgroundImage.url),onChange:toggleSuppressFilter}),jsxRuntimeExports.jsxs(InfoTip,{children:["When the color in the image is important (like in an image of a flag), you can suppress the filter that is used to make images compatible with dark mode.",!isGraphicalImage(backgroundImage.url)&&jsxRuntimeExports.jsxs("strong",{children:[" ","This option is only available for PNG and SVG images. Other types of images (e.g. JPG, GIF) never change in dark mode."]})]})]})]})}function isGraphicalImage(url){try{const{pathname}=new URL(url??"");return /\.(png|svg)$/.test(pathname)}catch{return false}}
1593
+ function DarkModeToggle({backgroundImage,onShowToggle,onSuppressToggle,editingDisabled=false}){const[showDarkMode,setShowDarkMode]=React.useState(false);const imageUrl=(()=>{try{return new URL(backgroundImage.url??"")}catch{return null}})();const suppressFilter=imageUrl?.searchParams.has("dark-mode")??false;const toggleDarkMode=()=>{onShowToggle(showDarkMode?undefined:"syl-dark");setShowDarkMode(!showDarkMode);};const toggleSuppressFilter=()=>{onSuppressToggle({backgroundImage:{...backgroundImage,url:setDarkModeOptionInUrl(suppressFilter?undefined:"off")}});};const setDarkModeOptionInUrl=darkModeSetting=>{try{const url=new URL(backgroundImage.url??"");if(darkModeSetting==="off"){url.searchParams.append("dark-mode","off");}else {url.searchParams.delete("dark-mode");}return url.toString()}catch{return backgroundImage.url??""}};return jsxRuntimeExports.jsxs("div",{className:styles$K.darkModeToggleContainer,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Show in Dark Mode",checked:showDarkMode,disabled:editingDisabled,onChange:toggleDarkMode}),jsxRuntimeExports.jsxs("div",{className:styles$K.darkModeSuppressionContainer,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Suppress Dark Mode Filter",checked:suppressFilter,disabled:editingDisabled||!isGraphicalImage(backgroundImage.url),onChange:toggleSuppressFilter}),jsxRuntimeExports.jsxs(InfoTip,{children:["When the color in the image is important (like in an image of a flag), you can suppress the filter that is used to make images compatible with dark mode.",!isGraphicalImage(backgroundImage.url)&&jsxRuntimeExports.jsxs("strong",{children:[" ","This option is only available for PNG and SVG images. Other types of images (e.g. JPG, GIF) never change in dark mode."]})]})]})]})}function isGraphicalImage(url){try{const{pathname}=new URL(url??"");return /\.(png|svg)$/.test(pathname)}catch{return false}}
1593
1594
 
1594
- var styles$K = {"decorativeToggleContainer":"perseus_Z9--Lqsc","flexRow":"perseus_H6OWRNo-"};
1595
+ var styles$J = {"decorativeToggleContainer":"perseus_Z9--Lqsc","flexRow":"perseus_H6OWRNo-"};
1595
1596
 
1596
- function DecorativeToggle({decorative,hasPopulatedFields,editingDisabled=false,onChange}){function handleDecorativeToggle(newValue){if(!newValue){onChange({decorative:false});return}if(!hasPopulatedFields){onChange({decorative:true});return}const shouldReset=window.confirm("Setting this image as decorative will automatically reset all other fields (title, caption, alt text, and long description). Do you want to continue?");if(shouldReset){onChange({decorative:true,alt:"",caption:undefined,title:undefined,longDescription:undefined});}}return jsxRuntimeExports.jsx("div",{className:styles$K.decorativeToggleContainer,children:jsxRuntimeExports.jsxs("div",{className:styles$K.flexRow,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Decorative",checked:decorative??false,disabled:editingDisabled,onChange:handleDecorativeToggle}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Mark this image as decorative and it will not have any alt text, description, title, or caption."})})]})})}
1597
+ function DecorativeToggle({decorative,hasPopulatedFields,editingDisabled=false,onChange}){function handleDecorativeToggle(newValue){if(!newValue){onChange({decorative:false});return}if(!hasPopulatedFields){onChange({decorative:true});return}const shouldReset=window.confirm("Setting this image as decorative will automatically reset all other fields (title, caption, alt text, and long description). Do you want to continue?");if(shouldReset){onChange({decorative:true,alt:"",caption:undefined,title:undefined,longDescription:undefined});}}return jsxRuntimeExports.jsx("div",{className:styles$J.decorativeToggleContainer,children:jsxRuntimeExports.jsxs("div",{className:styles$J.flexRow,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Decorative",checked:decorative??false,disabled:editingDisabled,onChange:handleDecorativeToggle}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Mark this image as decorative and it will not have any alt text, description, title, or caption."})})]})})}
1597
1598
 
1598
1599
  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})};
1599
1600
 
1600
- const LARGE_DIMENSION_THRESHOLD=1048576;function ImageScaleInput({backgroundImage,scale,editingDisabled=false,onChange}){const width=backgroundImage.width??0;const height=backgroundImage.height??0;const hasInvalidDimensions=isInvalidDimension(width)||isInvalidDimension(height);function handleScaleChange(newScale){const scaleNum=Number(newScale);if(isNaN(scaleNum)||scaleNum<=0){return}onChange({scale:scaleNum});}function handleScaledWidthChange(newScaledWidth){const newScaledWidthNum=Number(newScaledWidth);if(isNaN(newScaledWidthNum)||newScaledWidthNum<=0){return}if(width===0){return}const newScale=newScaledWidthNum/width;onChange({scale:newScale});}function handleScaledHeightChange(newScaledHeight){const newScaledHeightNum=Number(newScaledHeight);if(isNaN(newScaledHeightNum)||newScaledHeightNum<=0){return}if(height===0){return}const newScale=newScaledHeightNum/height;onChange({scale:newScale});}async function handleResetToOriginalSize(){if(!backgroundImage.url){return}const naturalSize=await Util.getImageSizeModern(backgroundImage.url);const[naturalWidth,naturalHeight]=naturalSize;if(naturalWidth===backgroundImage.width&&naturalHeight===backgroundImage.height){return}onChange({backgroundImage:{...backgroundImage,width:naturalWidth,height:naturalHeight}});}const hasLargeDimensions=width*height>LARGE_DIMENSION_THRESHOLD;return jsxRuntimeExports.jsxs("div",{className:styles$M.dimensionsContainer,children:[jsxRuntimeExports.jsxs(BodyMonospace,{children:["Natural size: ",width," x ",height]}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",size:"small",startIcon:arrowCounterClockwise,disabled:editingDisabled,onClick:handleResetToOriginalSize,children:"Recalculate natural size"}),hasLargeDimensions&&jsxRuntimeExports.jsx(Banner,{kind:"warning",text:"Large images may cause slow performance for learners. Please use a max size of 1024 x 1024."}),jsxRuntimeExports.jsx("div",{className:styles$M.horizontalLine}),hasInvalidDimensions&&jsxRuntimeExports.jsx(Banner,{kind:"warning",text:'Image size is invalid. Please use the "Recalculate natural size" button to enable scaling.',styles:{root:{marginBottom:sizing.size_080}}}),jsxRuntimeExports.jsx(LabeledField,{label:"Scale",description:"Use 1 to display image at original size.",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:scale.toString(),min:0,onChange:handleScaleChange,disabled:hasInvalidDimensions||editingDisabled}),styles:wbFieldStyles}),jsxRuntimeExports.jsxs("div",{className:styles$M.dimensionsFieldContainer,children:[jsxRuntimeExports.jsx(LabeledField,{label:"Scaled Width",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:(width*scale).toString(),min:0,onChange:handleScaledWidthChange,disabled:hasInvalidDimensions||editingDisabled}),styles:wbFieldStyles}),jsxRuntimeExports.jsx("span",{className:styles$M.xSpan,children:"x"}),jsxRuntimeExports.jsx(LabeledField,{label:"Scaled Height",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:(height*scale).toString(),min:0,onChange:handleScaledHeightChange,disabled:hasInvalidDimensions||editingDisabled}),styles:wbFieldStyles})]})]})}
1601
+ const LARGE_DIMENSION_THRESHOLD=1048576;function ImageScaleInput({backgroundImage,scale,editingDisabled=false,onChange}){const width=backgroundImage.width??0;const height=backgroundImage.height??0;const hasInvalidDimensions=isInvalidDimension(width)||isInvalidDimension(height);function handleScaleChange(newScale){const scaleNum=Number(newScale);if(isNaN(scaleNum)||scaleNum<=0){return}onChange({scale:scaleNum});}function handleScaledWidthChange(newScaledWidth){const newScaledWidthNum=Number(newScaledWidth);if(isNaN(newScaledWidthNum)||newScaledWidthNum<=0){return}if(width===0){return}const newScale=newScaledWidthNum/width;onChange({scale:newScale});}function handleScaledHeightChange(newScaledHeight){const newScaledHeightNum=Number(newScaledHeight);if(isNaN(newScaledHeightNum)||newScaledHeightNum<=0){return}if(height===0){return}const newScale=newScaledHeightNum/height;onChange({scale:newScale});}async function handleResetToOriginalSize(){if(!backgroundImage.url){return}const naturalSize=await Util.getImageSizeModern(backgroundImage.url);const[naturalWidth,naturalHeight]=naturalSize;if(naturalWidth===backgroundImage.width&&naturalHeight===backgroundImage.height){return}onChange({backgroundImage:{...backgroundImage,width:naturalWidth,height:naturalHeight}});}const hasLargeDimensions=width*height>LARGE_DIMENSION_THRESHOLD;return jsxRuntimeExports.jsxs("div",{className:styles$L.dimensionsContainer,children:[jsxRuntimeExports.jsxs(BodyMonospace,{children:["Natural size: ",width," x ",height]}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",size:"small",startIcon:arrowCounterClockwise,disabled:editingDisabled,onClick:handleResetToOriginalSize,children:"Recalculate natural size"}),hasLargeDimensions&&jsxRuntimeExports.jsx(Banner,{kind:"warning",text:"Large images may cause slow performance for learners. Please use a max size of 1024 x 1024."}),jsxRuntimeExports.jsx("div",{className:styles$L.horizontalLine}),hasInvalidDimensions&&jsxRuntimeExports.jsx(Banner,{kind:"warning",text:'Image size is invalid. Please use the "Recalculate natural size" button to enable scaling.',styles:{root:{marginBottom:sizing.size_080}}}),jsxRuntimeExports.jsx(LabeledField,{label:"Scale",description:"Use 1 to display image at original size.",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:scale.toString(),min:0,onChange:handleScaleChange,disabled:hasInvalidDimensions||editingDisabled}),styles:wbFieldStyles}),jsxRuntimeExports.jsxs("div",{className:styles$L.dimensionsFieldContainer,children:[jsxRuntimeExports.jsx(LabeledField,{label:"Scaled Width",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:(width*scale).toString(),min:0,onChange:handleScaledWidthChange,disabled:hasInvalidDimensions||editingDisabled}),styles:wbFieldStyles}),jsxRuntimeExports.jsx("span",{className:styles$L.xSpan,children:"x"}),jsxRuntimeExports.jsx(LabeledField,{label:"Scaled Height",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:(height*scale).toString(),min:0,onChange:handleScaledHeightChange,disabled:hasInvalidDimensions||editingDisabled}),styles:wbFieldStyles})]})]})}
1601
1602
 
1602
- const MIN_ALT_TEXT_LENGTH=8;const MAX_ALT_TEXT_LENGTH=125;const altTextTooLongError="Keep alt succinct at roughly 125 characters in length. Please pair the alt with a long description if you need significantly more text to sufficiently describe the image.";const altTextTooShortError="Add more detail to describe your image. While alt text should be brief, it must also describe the image well.";function ImageSettings({alt,apiOptions,backgroundImage,scale=1,caption,decorative,longDescription,title,onChange}){const[altFieldWarning,setAltFieldWarning]=React.useState(null);const[wbTheme,setWBTheme]=React.useState(undefined);if(!backgroundImage.url){return null}const editingDisabled=apiOptions?.editingDisabled??false;const hasPopulatedFields=Boolean(alt||caption||title||longDescription);function handleAltFieldChange(value){if(value.length===0){setAltFieldWarning(null);}else if(value.length>MAX_ALT_TEXT_LENGTH){setAltFieldWarning(altTextTooLongError);}else if(value.length>=MIN_ALT_TEXT_LENGTH){setAltFieldWarning(null);}onChange({alt:value});}function handleAltFieldBlur(value){if(value.length>0&&value.length<MIN_ALT_TEXT_LENGTH){setAltFieldWarning(altTextTooShortError);}}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Preview",field:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(DarkModeToggle,{editingDisabled:editingDisabled,backgroundImage:backgroundImage,onShowToggle:setWBTheme,onSuppressToggle:onChange}),jsxRuntimeExports.jsx(ImagePreview,{src:backgroundImage.url,alt:`Preview: ${alt||"No alt text"}`,width:backgroundImage.width,height:backgroundImage.height,wbTheme:wbTheme})]}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(ImageScaleInput,{backgroundImage:backgroundImage,scale:scale,editingDisabled:editingDisabled,onChange:onChange}),jsxRuntimeExports.jsx(DecorativeToggle,{decorative:decorative,hasPopulatedFields:hasPopulatedFields,editingDisabled:editingDisabled,onChange:onChange}),jsxRuntimeExports.jsx(LabeledField,{label:"Title",field:jsxRuntimeExports.jsx(TextArea,{value:title??"",onChange:value=>onChange({title:value}),disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStyles}),jsxRuntimeExports.jsxs("div",{className:styles$M.altTextFieldContainer,children:[jsxRuntimeExports.jsx(LabeledField,{label:"Alt text",description:"Summarize the image using up to 125 characters.",field:jsxRuntimeExports.jsx(TextArea,{value:alt??"",onBlur:e=>handleAltFieldBlur(e.target.value),onChange:handleAltFieldChange,disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStylesWithDescription}),jsxRuntimeExports.jsxs(BodyText,{size:"xsmall",tag:"span",style:wbStyles.characterCounter,children:[alt?.length??0," characters"]})]}),altFieldWarning&&jsxRuntimeExports.jsx(Banner,{kind:"warning",text:altFieldWarning,styles:{root:{marginBottom:sizing.size_080}}}),jsxRuntimeExports.jsx(LabeledField,{label:"Long description",field:jsxRuntimeExports.jsx(TextArea,{value:longDescription??"",onChange:value=>onChange({longDescription:value}),disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(LabeledField,{label:"Caption",field:jsxRuntimeExports.jsx(TextArea,{value:caption??"",onChange:value=>onChange({caption:value}),disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStyles})]})}const wbStyles=StyleSheet.create({characterCounter:{position:"absolute",insetBlockEnd:0,insetInlineEnd:8}});
1603
+ const MIN_ALT_TEXT_LENGTH=8;const MAX_ALT_TEXT_LENGTH=125;const altTextTooLongError="Keep alt succinct at roughly 125 characters in length. Please pair the alt with a long description if you need significantly more text to sufficiently describe the image.";const altTextTooShortError="Add more detail to describe your image. While alt text should be brief, it must also describe the image well.";function ImageSettings({alt,apiOptions,backgroundImage,scale=1,caption,decorative,longDescription,title,onChange}){const[altFieldWarning,setAltFieldWarning]=React.useState(null);const[wbTheme,setWBTheme]=React.useState(undefined);if(!backgroundImage.url){return null}const editingDisabled=apiOptions?.editingDisabled??false;const hasPopulatedFields=Boolean(alt||caption||title||longDescription);function handleAltFieldChange(value){if(value.length===0){setAltFieldWarning(null);}else if(value.length>MAX_ALT_TEXT_LENGTH){setAltFieldWarning(altTextTooLongError);}else if(value.length>=MIN_ALT_TEXT_LENGTH){setAltFieldWarning(null);}onChange({alt:value});}function handleAltFieldBlur(value){if(value.length>0&&value.length<MIN_ALT_TEXT_LENGTH){setAltFieldWarning(altTextTooShortError);}}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Preview",field:jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(DarkModeToggle,{editingDisabled:editingDisabled,backgroundImage:backgroundImage,onShowToggle:setWBTheme,onSuppressToggle:onChange}),jsxRuntimeExports.jsx(ImagePreview,{src:backgroundImage.url,alt:`Preview: ${alt||"No alt text"}`,width:backgroundImage.width,height:backgroundImage.height,wbTheme:wbTheme})]}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(ImageScaleInput,{backgroundImage:backgroundImage,scale:scale,editingDisabled:editingDisabled,onChange:onChange}),jsxRuntimeExports.jsx(DecorativeToggle,{decorative:decorative,hasPopulatedFields:hasPopulatedFields,editingDisabled:editingDisabled,onChange:onChange}),jsxRuntimeExports.jsx(LabeledField,{label:"Title",field:jsxRuntimeExports.jsx(TextArea,{value:title??"",onChange:value=>onChange({title:value}),disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStyles}),jsxRuntimeExports.jsxs("div",{className:styles$L.altTextFieldContainer,children:[jsxRuntimeExports.jsx(LabeledField,{label:"Alt text",description:"Summarize the image using up to 125 characters.",field:jsxRuntimeExports.jsx(TextArea,{value:alt??"",onBlur:e=>handleAltFieldBlur(e.target.value),onChange:handleAltFieldChange,disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStylesWithDescription}),jsxRuntimeExports.jsxs(BodyText,{size:"xsmall",tag:"span",style:wbStyles.characterCounter,children:[alt?.length??0," characters"]})]}),altFieldWarning&&jsxRuntimeExports.jsx(Banner,{kind:"warning",text:altFieldWarning,styles:{root:{marginBottom:sizing.size_080}}}),jsxRuntimeExports.jsx(LabeledField,{label:"Long description",field:jsxRuntimeExports.jsx(TextArea,{value:longDescription??"",onChange:value=>onChange({longDescription:value}),disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(LabeledField,{label:"Caption",field:jsxRuntimeExports.jsx(TextArea,{value:caption??"",onChange:value=>onChange({caption:value}),disabled:decorative||editingDisabled,autoResize:true}),styles:wbFieldStyles})]})}const wbStyles=StyleSheet.create({characterCounter:{position:"absolute",insetBlockEnd:0,insetInlineEnd:8}});
1603
1604
 
1604
1605
  const INTERNALLY_HOSTED_DOMAINS="("+"ka-.*.s3.amazonaws.com|"+"(fastly|cdn).kastatic.org|"+"khanacademy.org|"+"kasandbox.org"+")";const INTERNALLY_HOSTED_URL_RE=new RegExp("^(https?|web\\+graphie)://[^/]*"+INTERNALLY_HOSTED_DOMAINS);function ImageUrlInput({backgroundImage,onChange}){const uniqueId=React__default.useId();const urlId=`${uniqueId}-url`;const[urlFieldValue,setUrlFieldValue]=React__default.useState(backgroundImage.url||"");const[backgroundImageError,setBackgroundImageError]=React__default.useState(null);React__default.useEffect(()=>{setUrlFieldValue(backgroundImage.url||"");},[backgroundImage.url]);function setUrl(url,width,height){const image={...backgroundImage};image.url=url;image.width=width;image.height=height;const box=[image.width,image.height];onChange({backgroundImage:image,box:box});}async function onUrlChange(url){setBackgroundImageError(null);if(!url){setUrl(url,0,0);return}if(url===backgroundImage.url){return}if(url&&!INTERNALLY_HOSTED_URL_RE.test(url)){setBackgroundImageError("Images must be from sites hosted by Khan Academy. "+"Please input a Khan Academy-owned address, or use the "+"Add Image tool to rehost an existing image");return}try{const size=await Util.getImageSizeModern(url);setUrl(url,size[0],size[1]);}catch(error){setBackgroundImageError(`There was an error loading the image URL: ${JSON.stringify(error,null,2)}`);}}return jsxRuntimeExports.jsx(LabeledField,{label:"Image URL",description:"Paste an image or graphie image URL.",field:jsxRuntimeExports.jsx(TextField,{id:urlId,value:urlFieldValue,onBlur:e=>onUrlChange(e.target.value),onChange:value=>setUrlFieldValue(value)}),errorMessage:backgroundImageError,styles:wbFieldStylesWithDescription})}
1605
1606
 
1606
- class ImageEditor extends React.Component{serialize(){return EditorJsonify.serialize.call(this)}render(){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageUrlInput,{...this.props}),jsxRuntimeExports.jsx(ImageSettings,{...this.props})]})}}ImageEditor.displayName="ImageEditor";ImageEditor.widgetName="image";ImageEditor.defaultProps=imageLogic.defaultWidgetOptions;
1607
+ class ImageEditor extends React.Component{serialize(){return EditorJsonify.serialize.call(this)}render(){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageUrlInput,{...this.props}),jsxRuntimeExports.jsx(ImageSettings,{...this.props})]})}}ImageEditor.displayName="ImageEditor";ImageEditor.defaultProps=imageLogic.defaultWidgetOptions;
1607
1608
 
1608
- function Heading({title,isOpen,isCollapsible,onToggle}){return jsxRuntimeExports.jsx(Clickable,{style:[styles$J.container,!isCollapsible&&styles$J.notClickable],disabled:!isCollapsible,onClick:()=>isCollapsible&&onToggle?.(!isOpen),children:()=>jsxRuntimeExports.jsxs(View,{style:styles$J.heading,children:[jsxRuntimeExports.jsx(BodyText,{size:"small",weight:"bold",tag:"span",children:title}),isCollapsible&&jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:isOpen})]})})}const styles$J=StyleSheet.create({container:{marginBlockStart:spacing.small_12,marginInline:-10,backgroundColor:semanticColor.core.background.neutral.subtle,padding:spacing.xSmall_8,width:"calc(100% + 20px)"},heading:{flexDirection:"row",justifyContent:"space-between",userSelect:"none"},notClickable:{color:"inherit",cursor:"default"}});
1609
+ 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(BodyText,{size:"small",weight:"bold",tag:"span",children:title}),isCollapsible&&jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:isOpen})]})})}const styles$I=StyleSheet.create({container:{marginBlockStart:spacing.small_12,marginInline:-10,backgroundColor:semanticColor.core.background.neutral.subtle,padding:spacing.xSmall_8,width:"calc(100% + 20px)"},heading:{flexDirection:"row",justifyContent:"space-between",userSelect:"none"},notClickable:{color:"inherit",cursor:"default"}});
1609
1610
 
1610
- var styles$I = {"group":"perseus_Vniq-14O","wrapGroup":"perseus_8W6ltSJv","segment":"perseus_pYpuDydt"};
1611
+ var styles$H = {"group":"perseus_Vniq-14O","wrapGroup":"perseus_8W6ltSJv","segment":"perseus_pYpuDydt"};
1611
1612
 
1612
- function ToggleButton({selected,onClick,disabled=false,role="radio",children,style,"aria-label":ariaLabel}){return jsxRuntimeExports.jsx(Clickable,{role:role,"aria-checked":selected,"aria-label":ariaLabel,disabled:disabled,onClick:onClick,className:styles$I.segment,style:style,children:()=>children})}function SegmentedControl({options,selectedValue,onChange,disabled=false,"aria-label":ariaLabel}){return jsxRuntimeExports.jsx(View,{role:"radiogroup","aria-label":ariaLabel,className:styles$I.group,children:options.map(option=>jsxRuntimeExports.jsx(ToggleButton,{role:"radio",selected:option.value===selectedValue,"aria-label":option.ariaLabel,disabled:disabled,onClick:()=>onChange(option.value),children:option.label},option.value))})}function ToggleButtonGroup({options,selectedValues,onToggle,disabled=false,"aria-label":ariaLabel}){return jsxRuntimeExports.jsx(View,{role:"group","aria-label":ariaLabel,className:styles$I.wrapGroup,children:options.map(option=>jsxRuntimeExports.jsx(ToggleButton,{role:"checkbox",selected:selectedValues.includes(option.value),"aria-label":option.ariaLabel,disabled:disabled,onClick:()=>onToggle(option.value),children:option.label},option.value))})}
1613
+ function ToggleButton({selected,onClick,disabled=false,role="radio",children,style,"aria-label":ariaLabel}){return jsxRuntimeExports.jsx(Clickable,{role:role,"aria-checked":selected,"aria-label":ariaLabel,disabled:disabled,onClick:onClick,className:styles$H.segment,style:style,children:()=>children})}function SegmentedControl({options,selectedValue,onChange,disabled=false,"aria-label":ariaLabel}){return jsxRuntimeExports.jsx(View,{role:"radiogroup","aria-label":ariaLabel,className:styles$H.group,children:options.map(option=>jsxRuntimeExports.jsx(ToggleButton,{role:"radio",selected:option.value===selectedValue,"aria-label":option.ariaLabel,disabled:disabled,onClick:()=>onChange(option.value),children:option.label},option.value))})}function ToggleButtonGroup({options,selectedValues,onToggle,disabled=false,"aria-label":ariaLabel}){return jsxRuntimeExports.jsx(View,{role:"group","aria-label":ariaLabel,className:styles$H.wrapGroup,children:options.map(option=>jsxRuntimeExports.jsx(ToggleButton,{role:"checkbox",selected:selectedValues.includes(option.value),"aria-label":option.ariaLabel,disabled:disabled,onClick:()=>onToggle(option.value),children:option.label},option.value))})}
1613
1614
 
1614
- var styles$H = {"field":"perseus_SjB5EkqY","labelRow":"perseus_kGIonNza","inlineField":"perseus_AjUqaLV1"};
1615
+ var styles$G = {"field":"perseus_SjB5EkqY","labelRow":"perseus_kGIonNza","inlineField":"perseus_AjUqaLV1"};
1615
1616
 
1616
- const{NumberInput: NumberInput$b,TextInput: TextInput$2}=components;const{firstNumericalParse}=Util;const answerFormButtons=[{title:"Integers",value:"integer",content:"6"},{title:"Decimals",value:"decimal",content:"0.75"},{title:"Proper fractions",value:"proper",content:"⅗"},{title:"Improper fractions",value:"improper",content:"⁷⁄₄"},{title:"Mixed numbers",value:"mixed",content:"1¾"},{title:"Numbers with π",value:"pi",content:"π"}];const initAnswer=status=>{return {value:null,status:status,message:"",simplify:"required",answerForms:[],strict:false,maxError:null}};class NumericInputEditor extends React.Component{render(){const answers=this.props.answers;const editingDisabled=this.props.apiOptions.editingDisabled;const unsimplifiedAnswers=i=>jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[answers[i]["status"]!=="correct"&&jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are irrelevant for this status"}),answers[i]["status"]==="correct"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$H.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are"}),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsx("p",{children:'Normally select "ungraded". This will give the user a message saying the answer is correct but not simplified. The user will then have to simplify it and re-enter, but will not be penalized. (5th grade and after)'}),jsxRuntimeExports.jsx("p",{children:'Select "accepted" only if the user is not expected to know how to simplify fractions yet. (Anything prior to 5th grade)'}),jsxRuntimeExports.jsxs("p",{children:['Select "wrong" ',jsxRuntimeExports.jsx("em",{children:"only"})," if we are specifically assessing the ability to simplify."]})]})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Unsimplified answers are",disabled:editingDisabled,selectedValue:answers[i]["simplify"],onChange:value=>this.updateAnswer(i,{simplify:value}),options:[{value:"required",label:"Ungraded"},{value:"optional",label:"Accepted"},{value:"enforced",label:"Wrong"}]})]})]});const suggestedAnswerTypes=i=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$H.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Possible answer formats"}),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsx("p",{children:'Formats will be autoselected for you based on the given answer; to show no suggested formats and accept all types, simply have a decimal/integer be the answer. Values with π will have format "pi", and values that are fractions will have some subset (mixed will be "mixed" and "proper"; improper/proper will both be "improper" and "proper"). If you would like to specify that it is only a proper fraction (or only a mixed/improper fraction), deselect the other format. Except for specific cases, you should not need to change the autoselected formats.'}),jsxRuntimeExports.jsxs("p",{children:["To restrict the answer to ",jsxRuntimeExports.jsx("em",{children:"only"}),' an improper fraction (i.e. 7/4), select the improper fraction and toggle "strict" to true. This ',jsxRuntimeExports.jsx("b",{children:"will not"})," accept 1.75 as an answer."," "]}),jsxRuntimeExports.jsx("p",{children:"Unless you are testing that specific skill, please do not restrict the answer format."})]})]}),jsxRuntimeExports.jsx(ToggleButtonGroup,{"aria-label":"Possible answer formats",disabled:editingDisabled,selectedValues:answers[i]["answerForms"]??[],onToggle:value=>this.onToggleAnswerForm(i,value),options:answerFormButtons.map(format=>({value:format.value,label:format.content,ariaLabel:format.title}))})]}),jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer formats are"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Answer formats are",disabled:editingDisabled,selectedValue:answers[i]["strict"]?"required":"suggested",onChange:value=>this.updateAnswer(i,{strict:value==="required"}),options:[{value:"suggested",label:"Suggested"},{value:"required",label:"Required"}]})]})]});const inputSize=jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$H.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Width"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Use size "Normal" for all text boxes, unless there are multiple text boxes in one line and the answer area is too narrow to fit them.'})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Width",disabled:editingDisabled,selectedValue:this.props.size,onChange:value=>this.change("size")(value),options:[{value:"normal",label:"Normal (80px)"},{value:"small",label:"Small (40px)"}]})]});const labelText=jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$H.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer Field Aria label"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Text to describe the Answer Field for screenreader users."})})]}),jsxRuntimeExports.jsx(TextInput$2,{labelText:"aria label",value:this.props.labelText,onChange:this.change("labelText")})]});const coefficientCheck=jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$H.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Number style"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"A coefficient style number allows the student to use - for -1 and an empty string to mean 1."})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Number style",disabled:editingDisabled,selectedValue:this.props.coefficient?"coefficient":"standard",onChange:value=>this.props.onChange({coefficient:value==="coefficient"}),options:[{value:"standard",label:"Standard"},{value:"coefficient",label:"Coefficient"}]})]});const instructions={wrong:"(address the mistake/misconception)",ungraded:"(explain in detail to avoid confusion)",correct:"(reinforce the user's understanding)"};const generateInputAnswerEditors=()=>answers.map((answer,i)=>{const editor=jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:answer.message||"",placeholder:"Why is this answer "+answer.status+"? "+instructions[answer.status],widgetEnabled:false,onChange:newProps=>{if("content"in newProps){this.updateAnswer(i,{message:newProps.content});}}});const statusProper=answer.status.charAt(0).toUpperCase()+answer.status.slice(1);const answerFormat=(answer.answerForms||[]).at(-1);const answerString=KhanMath.toNumericString(answer.value??0,answerFormat);const answerRangeText=answer.maxError?`\xb1 ${KhanMath.toNumericString(answer.maxError,answerFormat)}`:"";const answerHeading=answer.value===null?"New Answer":`${statusProper} answer: ${answerString} ${answerRangeText}`;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-row answer-option",children:jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:this.state.showAnswerDetails[i],onToggle:()=>{this.onToggleAnswers(i);},header:jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:answerHeading}),children:[jsxRuntimeExports.jsxs("div",{className:"input-answer-editor-value-container"+(answer.maxError?" with-max-error":""),children:[jsxRuntimeExports.jsxs(View,{tag:"label",className:styles$H.inlineField,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"User input"}),jsxRuntimeExports.jsx(NumberInput$b,{value:answer.value,className:"numeric-input-value",placeholder:"answer",format:_.last(answer.answerForms||[]),onFormatChange:(newValue,format)=>{let forms;if(format==="pi"){forms=["pi"];}else if(format==="mixed"){forms=["proper","mixed"];}else if(format==="proper"||format==="improper"){forms=["proper","improper"];}this.updateAnswer(i,{value:firstNumericalParse(newValue),answerForms:forms});},onChange:newValue=>{this.updateAnswer(i,{value:firstNumericalParse(newValue)});}})]}),jsxRuntimeExports.jsx("span",{className:"max-error-plusmn",children:"±"}),jsxRuntimeExports.jsx(NumberInput$b,{className:"max-error-input-value",placeholder:0,value:answers[i]["maxError"],format:_.last(answer.answerForms||[]),onChange:this.updateAnswer(i,"maxError")})]}),jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Status"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Status",disabled:editingDisabled,selectedValue:answers[i]["status"],onChange:value=>this.onEvaluationChange(i,value),options:[{value:"correct",label:"Correct"},{value:"wrong",label:"Wrong"},{value:"ungraded",label:"Ungraded"}]})]}),unsimplifiedAnswers(i),jsxRuntimeExports.jsxs(View,{className:styles$H.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"(Articles only) Message shown to user"}),editor]}),suggestedAnswerTypes(i),jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,"aria-label":`Delete ${answerHeading}`,className:"delete-item-button",disabled:editingDisabled,onClick:()=>{this.onTrashAnswer(i);},kind:"tertiary",children:"Delete"})]})},i)});return jsxRuntimeExports.jsxs("div",{className:"perseus-input-number-editor",children:[jsxRuntimeExports.jsx(Heading,{title:"General Settings",isCollapsible:true,isOpen:this.state.showSettings,onToggle:this.onToggleHeading("Settings")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showSettings?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[inputSize,jsxRuntimeExports.jsxs("label",{children:["Text alignment",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:this.props.textAlign,onChange:value=>{this.props.onChange({textAlign:value});},options:{left:"Left",center:"Center",right:"Right"},placeholder:"Select text alignment"})]}),coefficientCheck,labelText]})}),jsxRuntimeExports.jsx(Heading,{title:"Answers",isCollapsible:true,isOpen:this.state.showAnswers,onToggle:this.onToggleHeading("Answers")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showAnswers?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[generateInputAnswerEditors(),jsxRuntimeExports.jsx(Button,{kind:"tertiary",disabled:editingDisabled,onClick:this.addAnswer,children:"Add new answer"})]})})]})}constructor(props){super(props),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.onToggleAnswers=answerIndex=>{const showAnswerDetails=this.state.showAnswerDetails.slice();showAnswerDetails[answerIndex]=!showAnswerDetails[answerIndex];this.setState({showAnswerDetails:showAnswerDetails});},this.onToggleAnswerForm=(answerIndex,answerForm)=>{let answerForms=[...this.props.answers[answerIndex]["answerForms"]??[]];const formSelected=answerForms.includes(answerForm);if(!formSelected){answerForms.push(answerForm);}else {answerForms=answerForms.filter(form=>form!==answerForm);}const updateFn=this.updateAnswer(answerIndex,"answerForms");if(updateFn){updateFn(answerForms);}},this.onToggleHeading=accordionName=>{return ()=>{const toggleName=`show${accordionName}`;const newState={...this.state};newState[toggleName]=!newState[toggleName];this.setState(newState);}},this.onTrashAnswer=choiceIndex=>{if(choiceIndex>=0&&choiceIndex<this.props.answers.length){const answers=this.props.answers.slice(0);answers.splice(choiceIndex,1);this.props.onChange({answers:answers});}},this.onSpace=(e,callback,...args)=>{if(e.key===" "){e.preventDefault();callback.apply(this,args);}},this.onStatusChange=choiceIndex=>{const statuses=["wrong","ungraded","correct"];const answers=this.props.answers;const i=statuses.indexOf(answers[choiceIndex].status);const newStatus=statuses[(i+1)%statuses.length];this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.onEvaluationChange=(choiceIndex,newStatus)=>{this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.updateAnswer=(choiceIndex,update)=>{if(!_.isObject(update)){return _.partial((choiceIndex,key,value)=>{const update={};update[key]=value;this.updateAnswer(choiceIndex,update);},choiceIndex,update)}let answers=[...this.props.answers];if(choiceIndex===answers.length){const lastAnswer=initAnswer(this.state.lastStatus);answers=answers.concat(lastAnswer);}answers[choiceIndex]=_.extend({},answers[choiceIndex],update);this.props.onChange({answers:answers});},this.addAnswer=()=>{const lastAnswer=initAnswer(this.state.lastStatus);const answers=this.props.answers.concat(lastAnswer);const showAnswerDetails=this.state.showAnswerDetails.concat(true);this.setState({showAnswerDetails:showAnswerDetails});this.props.onChange({answers:answers});},this.getSaveWarnings=()=>{const warnings=[];if(_.contains(_.pluck(this.props.answers,"value"),"")){warnings.push("One or more answers is empty");}this.props.answers.forEach((answer,i)=>{const formatError=answer.strict&&(!answer.answerForms||answer.answerForms.length===0);if(formatError){warnings.push(`Answer ${i+1} is set to string format `+"matching, but no format was selected");}});return warnings},this.serialize=()=>{return EditorJsonify.serialize.call(this)};this.state={lastStatus:"wrong",showAnswerDetails:Array(this.props.answers.length).fill(true),showSettings:true,showAnswers:true};}}NumericInputEditor.widgetName="numeric-input";NumericInputEditor.displayName="NumericInputEditor";NumericInputEditor.defaultProps={...numericInputLogic.defaultWidgetOptions};
1617
+ const{NumberInput: NumberInput$b,TextInput: TextInput$2}=components;const{firstNumericalParse}=Util;const answerFormButtons=[{title:"Integers",value:"integer",content:"6"},{title:"Decimals",value:"decimal",content:"0.75"},{title:"Proper fractions",value:"proper",content:"⅗"},{title:"Improper fractions",value:"improper",content:"⁷⁄₄"},{title:"Mixed numbers",value:"mixed",content:"1¾"},{title:"Numbers with π",value:"pi",content:"π"}];const initAnswer=status=>{return {value:null,status:status,message:"",simplify:"required",answerForms:[],strict:false,maxError:null}};class NumericInputEditor extends React.Component{render(){const answers=this.props.answers;const editingDisabled=this.props.apiOptions.editingDisabled;const unsimplifiedAnswers=i=>jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[answers[i]["status"]!=="correct"&&jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are irrelevant for this status"}),answers[i]["status"]==="correct"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$G.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Unsimplified answers are"}),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsx("p",{children:'Normally select "ungraded". This will give the user a message saying the answer is correct but not simplified. The user will then have to simplify it and re-enter, but will not be penalized. (5th grade and after)'}),jsxRuntimeExports.jsx("p",{children:'Select "accepted" only if the user is not expected to know how to simplify fractions yet. (Anything prior to 5th grade)'}),jsxRuntimeExports.jsxs("p",{children:['Select "wrong" ',jsxRuntimeExports.jsx("em",{children:"only"})," if we are specifically assessing the ability to simplify."]})]})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Unsimplified answers are",disabled:editingDisabled,selectedValue:answers[i]["simplify"],onChange:value=>this.updateAnswer(i,{simplify:value}),options:[{value:"required",label:"Ungraded"},{value:"optional",label:"Accepted"},{value:"enforced",label:"Wrong"}]})]})]});const suggestedAnswerTypes=i=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$G.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Possible answer formats"}),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsx("p",{children:'Formats will be autoselected for you based on the given answer; to show no suggested formats and accept all types, simply have a decimal/integer be the answer. Values with π will have format "pi", and values that are fractions will have some subset (mixed will be "mixed" and "proper"; improper/proper will both be "improper" and "proper"). If you would like to specify that it is only a proper fraction (or only a mixed/improper fraction), deselect the other format. Except for specific cases, you should not need to change the autoselected formats.'}),jsxRuntimeExports.jsxs("p",{children:["To restrict the answer to ",jsxRuntimeExports.jsx("em",{children:"only"}),' an improper fraction (i.e. 7/4), select the improper fraction and toggle "strict" to true. This ',jsxRuntimeExports.jsx("b",{children:"will not"})," accept 1.75 as an answer."," "]}),jsxRuntimeExports.jsx("p",{children:"Unless you are testing that specific skill, please do not restrict the answer format."})]})]}),jsxRuntimeExports.jsx(ToggleButtonGroup,{"aria-label":"Possible answer formats",disabled:editingDisabled,selectedValues:answers[i]["answerForms"]??[],onToggle:value=>this.onToggleAnswerForm(i,value),options:answerFormButtons.map(format=>({value:format.value,label:format.content,ariaLabel:format.title}))})]}),jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer formats are"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Answer formats are",disabled:editingDisabled,selectedValue:answers[i]["strict"]?"required":"suggested",onChange:value=>this.updateAnswer(i,{strict:value==="required"}),options:[{value:"suggested",label:"Suggested"},{value:"required",label:"Required"}]})]})]});const inputSize=jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$G.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Width"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Use size "Normal" for all text boxes, unless there are multiple text boxes in one line and the answer area is too narrow to fit them.'})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Width",disabled:editingDisabled,selectedValue:this.props.size,onChange:value=>this.change("size")(value),options:[{value:"normal",label:"Normal (80px)"},{value:"small",label:"Small (40px)"}]})]});const labelText=jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$G.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Answer Field Aria label"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Text to describe the Answer Field for screenreader users."})})]}),jsxRuntimeExports.jsx(TextInput$2,{labelText:"aria label",value:this.props.labelText,onChange:this.change("labelText")})]});const coefficientCheck=jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsxs(View,{className:styles$G.labelRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Number style"}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"A coefficient style number allows the student to use - for -1 and an empty string to mean 1."})})]}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Number style",disabled:editingDisabled,selectedValue:this.props.coefficient?"coefficient":"standard",onChange:value=>this.props.onChange({coefficient:value==="coefficient"}),options:[{value:"standard",label:"Standard"},{value:"coefficient",label:"Coefficient"}]})]});const instructions={wrong:"(address the mistake/misconception)",ungraded:"(explain in detail to avoid confusion)",correct:"(reinforce the user's understanding)"};const generateInputAnswerEditors=()=>answers.map((answer,i)=>{const editor=jsxRuntimeExports.jsx(Editor,{apiOptions:this.props.apiOptions,content:answer.message||"",placeholder:"Why is this answer "+answer.status+"? "+instructions[answer.status],widgetEnabled:false,onChange:newProps=>{if("content"in newProps){this.updateAnswer(i,{message:newProps.content});}}});const statusProper=answer.status.charAt(0).toUpperCase()+answer.status.slice(1);const answerFormat=(answer.answerForms||[]).at(-1);const answerString=KhanMath.toNumericString(answer.value??0,answerFormat);const answerRangeText=answer.maxError?`\xb1 ${KhanMath.toNumericString(answer.maxError,answerFormat)}`:"";const answerHeading=answer.value===null?"New Answer":`${statusProper} answer: ${answerString} ${answerRangeText}`;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-row answer-option",children:jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:this.state.showAnswerDetails[i],onToggle:()=>{this.onToggleAnswers(i);},header:jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:answerHeading}),children:[jsxRuntimeExports.jsxs("div",{className:"input-answer-editor-value-container"+(answer.maxError?" with-max-error":""),children:[jsxRuntimeExports.jsxs(View,{tag:"label",className:styles$G.inlineField,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"User input"}),jsxRuntimeExports.jsx(NumberInput$b,{value:answer.value,className:"numeric-input-value",placeholder:"answer",format:_.last(answer.answerForms||[]),onFormatChange:(newValue,format)=>{let forms;if(format==="pi"){forms=["pi"];}else if(format==="mixed"){forms=["proper","mixed"];}else if(format==="proper"||format==="improper"){forms=["proper","improper"];}this.updateAnswer(i,{value:firstNumericalParse(newValue),answerForms:forms});},onChange:newValue=>{this.updateAnswer(i,{value:firstNumericalParse(newValue)});}})]}),jsxRuntimeExports.jsx("span",{className:"max-error-plusmn",children:"±"}),jsxRuntimeExports.jsx(NumberInput$b,{className:"max-error-input-value",placeholder:0,value:answers[i]["maxError"],format:_.last(answer.answerForms||[]),onChange:this.updateAnswer(i,"maxError")})]}),jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"Status"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Status",disabled:editingDisabled,selectedValue:answers[i]["status"],onChange:value=>this.onEvaluationChange(i,value),options:[{value:"correct",label:"Correct"},{value:"wrong",label:"Wrong"},{value:"ungraded",label:"Ungraded"}]})]}),unsimplifiedAnswers(i),jsxRuntimeExports.jsxs(View,{className:styles$G.field,children:[jsxRuntimeExports.jsx(BodyText,{weight:"semi",children:"(Articles only) Message shown to user"}),editor]}),suggestedAnswerTypes(i),jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,"aria-label":`Delete ${answerHeading}`,className:"delete-item-button",disabled:editingDisabled,onClick:()=>{this.onTrashAnswer(i);},kind:"tertiary",children:"Delete"})]})},i)});return jsxRuntimeExports.jsxs("div",{className:"perseus-input-number-editor",children:[jsxRuntimeExports.jsx(Heading,{title:"General Settings",isCollapsible:true,isOpen:this.state.showSettings,onToggle:this.onToggleHeading("Settings")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showSettings?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[inputSize,jsxRuntimeExports.jsxs("label",{children:["Text alignment",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:this.props.textAlign,onChange:value=>{this.props.onChange({textAlign:value});},options:{left:"Left",center:"Center",right:"Right"},placeholder:"Select text alignment"})]}),coefficientCheck,labelText]})}),jsxRuntimeExports.jsx(Heading,{title:"Answers",isCollapsible:true,isOpen:this.state.showAnswers,onToggle:this.onToggleHeading("Answers")}),jsxRuntimeExports.jsx("div",{className:`perseus-editor-accordion-container ${this.state.showAnswers?"expanded":"collapsed"}`,children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-accordion-content",children:[generateInputAnswerEditors(),jsxRuntimeExports.jsx(Button,{kind:"tertiary",disabled:editingDisabled,onClick:this.addAnswer,children:"Add new answer"})]})})]})}constructor(props){super(props),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this.onToggleAnswers=answerIndex=>{const showAnswerDetails=this.state.showAnswerDetails.slice();showAnswerDetails[answerIndex]=!showAnswerDetails[answerIndex];this.setState({showAnswerDetails:showAnswerDetails});},this.onToggleAnswerForm=(answerIndex,answerForm)=>{let answerForms=[...this.props.answers[answerIndex]["answerForms"]??[]];const formSelected=answerForms.includes(answerForm);if(!formSelected){answerForms.push(answerForm);}else {answerForms=answerForms.filter(form=>form!==answerForm);}const updateFn=this.updateAnswer(answerIndex,"answerForms");if(updateFn){updateFn(answerForms);}},this.onToggleHeading=accordionName=>{return ()=>{const toggleName=`show${accordionName}`;const newState={...this.state};newState[toggleName]=!newState[toggleName];this.setState(newState);}},this.onTrashAnswer=choiceIndex=>{if(choiceIndex>=0&&choiceIndex<this.props.answers.length){const answers=this.props.answers.slice(0);answers.splice(choiceIndex,1);this.props.onChange({answers:answers});}},this.onSpace=(e,callback,...args)=>{if(e.key===" "){e.preventDefault();callback.apply(this,args);}},this.onStatusChange=choiceIndex=>{const statuses=["wrong","ungraded","correct"];const answers=this.props.answers;const i=statuses.indexOf(answers[choiceIndex].status);const newStatus=statuses[(i+1)%statuses.length];this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.onEvaluationChange=(choiceIndex,newStatus)=>{this.updateAnswer(choiceIndex,{status:newStatus,simplify:newStatus==="correct"?"required":"accepted"});},this.updateAnswer=(choiceIndex,update)=>{if(!_.isObject(update)){return _.partial((choiceIndex,key,value)=>{const update={};update[key]=value;this.updateAnswer(choiceIndex,update);},choiceIndex,update)}let answers=[...this.props.answers];if(choiceIndex===answers.length){const lastAnswer=initAnswer(this.state.lastStatus);answers=answers.concat(lastAnswer);}answers[choiceIndex]=_.extend({},answers[choiceIndex],update);this.props.onChange({answers:answers});},this.addAnswer=()=>{const lastAnswer=initAnswer(this.state.lastStatus);const answers=this.props.answers.concat(lastAnswer);const showAnswerDetails=this.state.showAnswerDetails.concat(true);this.setState({showAnswerDetails:showAnswerDetails});this.props.onChange({answers:answers});},this.getSaveWarnings=()=>{const warnings=[];if(_.contains(_.pluck(this.props.answers,"value"),"")){warnings.push("One or more answers is empty");}this.props.answers.forEach((answer,i)=>{const formatError=answer.strict&&(!answer.answerForms||answer.answerForms.length===0);if(formatError){warnings.push(`Answer ${i+1} is set to string format `+"matching, but no format was selected");}});return warnings},this.serialize=()=>{return EditorJsonify.serialize.call(this)};this.state={lastStatus:"wrong",showAnswerDetails:Array(this.props.answers.length).fill(true),showSettings:true,showAnswers:true};}}NumericInputEditor.displayName="NumericInputEditor";NumericInputEditor.defaultProps={...numericInputLogic.defaultWidgetOptions};
1617
1618
 
1618
- class InputNumberEditor extends NumericInputEditor{}InputNumberEditor.widgetName="input-number";
1619
+ class InputNumberEditor extends NumericInputEditor{}
1619
1620
 
1620
1621
  const{InlineIcon}=components;class ElementContainer extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-interaction-element",children:[jsxRuntimeExports.jsxs("a",{href:"#",className:"perseus-interaction-element-title "+(this.state.show?"open":"closed"),onClick:this.toggle,children:[this.state.show?jsxRuntimeExports.jsx(InlineIcon,{...iconChevronDown}):jsxRuntimeExports.jsx(InlineIcon,{...iconChevronRight}),this.props.title]}),jsxRuntimeExports.jsxs("div",{className:"perseus-interaction-element-content "+(this.state.show?"enter":"leave"),children:[this.props.children,(this.props.onUp!=null||this.props.onDown!=null||this.props.onDelete!=null)&&jsxRuntimeExports.jsxs("div",{className:"edit-controls",children:[this.props.onUp!=null&&jsxRuntimeExports.jsx("button",{onClick:this.props.onUp,children:jsxRuntimeExports.jsx(InlineIcon,{...iconCircleArrowUp})}),this.props.onDown!=null&&jsxRuntimeExports.jsx("button",{onClick:this.props.onDown,children:jsxRuntimeExports.jsx(InlineIcon,{...iconCircleArrowDown})}),this.props.onDelete!=null&&jsxRuntimeExports.jsx("button",{onClick:this.props.onDelete,children:jsxRuntimeExports.jsx(InlineIcon,{...iconTrash})})]})]})]})}constructor(props){super(props),this.toggle=e=>{e.preventDefault();this.setState({show:!this.state.show});};this.state={show:props.initiallyVisible};}}ElementContainer.defaultProps={initiallyVisible:false,title:"More"};
1621
1622
 
@@ -1623,7 +1624,7 @@ const{ButtonGroup: ButtonGroup$5}=components;const COLORS=[KhanColors.BLACK,Khan
1623
1624
 
1624
1625
  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:""};
1625
1626
 
1626
- 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$G.outerWrapper,children:jsxRuntimeExports.jsx("span",{ref:mathFieldWrapperRef,className:"perseus-math-input mq-editable-field mq-math-mode"})})}const styles$G=StyleSheet.create({outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:semanticColor.core.border.neutral.default,borderRadius:3,background:semanticColor.core.background.base.default}});
1627
+ 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$F.outerWrapper,children:jsxRuntimeExports.jsx("span",{ref:mathFieldWrapperRef,className:"perseus-math-input mq-editable-field mq-math-mode"})})}const styles$F=StyleSheet.create({outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:semanticColor.core.border.neutral.default,borderRadius:3,background:semanticColor.core.background.base.default}});
1627
1628
 
1628
1629
  const{NumberInput: NumberInput$a}=components;class FunctionEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();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$a,{value:this.props.strokeWidth,placeholder:2,onChange:this.change("strokeWidth")})]})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}FunctionEditor.defaultProps={value:"x",rangeMin:"-10",rangeMax:"10",color:KhanColors.BLUE,strokeDasharray:"",strokeWidth:2};
1629
1630
 
@@ -1645,187 +1646,181 @@ class PointEditor extends React.Component{render(){const{TeX}=Dependencies.getDe
1645
1646
 
1646
1647
  class RectangleEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Bottom left: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordX,onChange:this.change("coordX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordY,onChange:this.change("coordY")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Width:"," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.width,onChange:this.change("width")})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Height:"," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.height,onChange:this.change("height")})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,lightColors:true,onChange:this.change("color")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:"You want a border? Sorry, draw your own."})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}RectangleEditor.defaultProps={coordX:"-5",coordY:"5",width:"2",height:"3",color:KhanColors.LIGHT_BLUE};
1647
1648
 
1648
- const{unescapeMathMode}=Util;const defaultOptionsByElementType={point:PointEditor.defaultProps,line:LineEditor.defaultProps,"movable-point":MovablePointEditor.defaultProps,"movable-line":MovableLineEditor.defaultProps,function:FunctionEditor.defaultProps,parametric:ParametricEditor.defaultProps,label:LabelEditor.defaultProps,rectangle:RectangleEditor.defaultProps};class InteractionEditor extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({usedVarSubscripts:this._getAllVarSubscripts(nextProps.elements),usedFunctionNames:this._getAllFunctionNames(nextProps.elements)});}_getAllVarSubscripts(elements){const movableLines=elements.filter(element=>element.type==="movable-line");return elements.filter(element=>element.type==="movable-point").map(element=>element.options.varSubscript).concat(movableLines.map(element=>element.options.startSubscript)).concat(movableLines.map(element=>element.options.endSubscript))}_getAllFunctionNames(elements){return elements.filter(element=>element.type==="function").map(element=>element.options.funcName)}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-interaction-editor",children:[jsxRuntimeExports.jsxs(ElementContainer,{title:"Grid settings",children:[jsxRuntimeExports.jsx(GraphSettings,{editableSettings:["canvas","graph"],box:this.props.graph.box,labels:this.props.graph.labels,range:this.props.graph.range,step:this.props.graph.tickStep,gridStep:this.props.graph.gridStep,markings:this.props.graph.markings,onChange:this._updateGraphProps}),jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:this.props.graph.valid!==true&&jsxRuntimeExports.jsx("div",{children:this.props.graph.valid})})]}),this.props.elements.map((element,n)=>{if(element.type==="movable-point"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Movable point"," ",jsxRuntimeExports.jsx(TeX,{children:"(x_{"+element.options.varSubscript+"}, y_{"+element.options.varSubscript+"})"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(MovablePointEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="movable-line"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Movable line"," ",jsxRuntimeExports.jsx(TeX,{children:"(x_{"+element.options.startSubscript+"}, y_{"+element.options.startSubscript+"})"})," ","to"," ",jsxRuntimeExports.jsx(TeX,{children:"(x_{"+element.options.endSubscript+"}, y_{"+element.options.endSubscript+"})"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(MovableLineEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="point"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Point"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.coordX+", "+element.options.coordY+")"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(PointEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="line"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Line"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.startX+", "+element.options.startY+")"})," ","to"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.endX+", "+element.options.endY+")"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(LineEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="function"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Function"," ",jsxRuntimeExports.jsx(TeX,{children:element.options.funcName+"(x) = "+element.options.value})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(FunctionEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="parametric"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsx("span",{children:"Parametric"}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(ParametricEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="label"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Label"," ",jsxRuntimeExports.jsx(TeX,{children:unescapeMathMode(element.options.label)})," "]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(LabelEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="rectangle"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Rectangle"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.coordX+", "+element.options.coordY+")"})," — ",jsxRuntimeExports.jsx(TeX,{children:element.options.width+" \\times "+element.options.height})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(RectangleEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-interaction-editor-select-element",children:jsxRuntimeExports.jsxs("select",{onChange:this._addNewElement,children:[jsxRuntimeExports.jsxs("option",{value:"",children:["Add an element","…"]}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"point",children:"Point"}),jsxRuntimeExports.jsx("option",{value:"line",children:"Line segment"}),jsxRuntimeExports.jsx("option",{value:"function",children:"Function plot"}),jsxRuntimeExports.jsx("option",{value:"parametric",children:"Parametric plot"}),jsxRuntimeExports.jsx("option",{value:"label",children:"Label"}),jsxRuntimeExports.jsx("option",{value:"rectangle",children:"Rectangle"}),jsxRuntimeExports.jsx("option",{value:"movable-point",children:"★ Movable point"}),jsxRuntimeExports.jsx("option",{value:"movable-line",children:"★ Movable line segment"})]})})]})}constructor(...args){super(...args),this.state={usedVarSubscripts:this._getAllVarSubscripts(this.props.elements),usedFunctionNames:this._getAllFunctionNames(this.props.elements)},this._updateGraphProps=newProps=>{const{step,...rest}=newProps;this.props.onChange({graph:{...this.props.graph,...rest,tickStep:step}});},this._addNewElement=e=>{const elementType=e.target.value;if(elementType===""){return}e.target.value="";const newElement={type:elementType,key:elementType+"-"+(Math.random()*0xffffff<<0).toString(16),options:{...defaultOptionsByElementType[elementType]}};let nextSubscript;if(elementType==="movable-point"){nextSubscript=Math.max(...this.state.usedVarSubscripts,-1)+1;newElement.options.varSubscript=nextSubscript;}else if(elementType==="movable-line"){nextSubscript=Math.max(...this.state.usedVarSubscripts,-1)+1;newElement.options.startSubscript=nextSubscript;newElement.options.endSubscript=nextSubscript+1;}else if(elementType==="function"){const nextLetter=String.fromCharCode(Math.max(...this.state.usedFunctionNames.map(c=>c.charCodeAt(0)),"e".charCodeAt(0))+1);newElement.options.funcName=nextLetter;}this.props.onChange({elements:this.props.elements.concat(newElement)});},this._deleteElement=index=>{const element=this.props.elements[index];this.props.onChange({elements:this.props.elements.filter(e=>e!==element)});},this._moveElementUp=index=>{const element=this.props.elements[index];const newElements=this.props.elements.filter(e=>e!==element);newElements.splice(index-1,0,element);this.props.onChange({elements:newElements});},this._moveElementDown=index=>{const element=this.props.elements[index];const newElements=this.props.elements.filter(e=>e!==element);newElements.splice(index+1,0,element);this.props.onChange({elements:newElements});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}InteractionEditor.widgetName="interaction";InteractionEditor.defaultProps=interactionLogic.defaultWidgetOptions;
1649
+ const{unescapeMathMode}=Util;const defaultOptionsByElementType={point:PointEditor.defaultProps,line:LineEditor.defaultProps,"movable-point":MovablePointEditor.defaultProps,"movable-line":MovableLineEditor.defaultProps,function:FunctionEditor.defaultProps,parametric:ParametricEditor.defaultProps,label:LabelEditor.defaultProps,rectangle:RectangleEditor.defaultProps};class InteractionEditor extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({usedVarSubscripts:this._getAllVarSubscripts(nextProps.elements),usedFunctionNames:this._getAllFunctionNames(nextProps.elements)});}_getAllVarSubscripts(elements){const movableLines=elements.filter(element=>element.type==="movable-line");return elements.filter(element=>element.type==="movable-point").map(element=>element.options.varSubscript).concat(movableLines.map(element=>element.options.startSubscript)).concat(movableLines.map(element=>element.options.endSubscript))}_getAllFunctionNames(elements){return elements.filter(element=>element.type==="function").map(element=>element.options.funcName)}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-interaction-editor",children:[jsxRuntimeExports.jsxs(ElementContainer,{title:"Grid settings",children:[jsxRuntimeExports.jsx(GraphSettings,{editableSettings:["canvas","graph"],box:this.props.graph.box,labels:this.props.graph.labels,range:this.props.graph.range,step:this.props.graph.tickStep,gridStep:this.props.graph.gridStep,markings:this.props.graph.markings,onChange:this._updateGraphProps}),jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:this.props.graph.valid!==true&&jsxRuntimeExports.jsx("div",{children:this.props.graph.valid})})]}),this.props.elements.map((element,n)=>{if(element.type==="movable-point"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Movable point"," ",jsxRuntimeExports.jsx(TeX,{children:"(x_{"+element.options.varSubscript+"}, y_{"+element.options.varSubscript+"})"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(MovablePointEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="movable-line"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Movable line"," ",jsxRuntimeExports.jsx(TeX,{children:"(x_{"+element.options.startSubscript+"}, y_{"+element.options.startSubscript+"})"})," ","to"," ",jsxRuntimeExports.jsx(TeX,{children:"(x_{"+element.options.endSubscript+"}, y_{"+element.options.endSubscript+"})"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(MovableLineEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="point"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Point"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.coordX+", "+element.options.coordY+")"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(PointEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="line"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Line"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.startX+", "+element.options.startY+")"})," ","to"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.endX+", "+element.options.endY+")"})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(LineEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="function"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Function"," ",jsxRuntimeExports.jsx(TeX,{children:element.options.funcName+"(x) = "+element.options.value})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(FunctionEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="parametric"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsx("span",{children:"Parametric"}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(ParametricEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="label"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Label"," ",jsxRuntimeExports.jsx(TeX,{children:unescapeMathMode(element.options.label)})," "]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(LabelEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}if(element.type==="rectangle"){return jsxRuntimeExports.jsx(ElementContainer,{title:jsxRuntimeExports.jsxs("span",{children:["Rectangle"," ",jsxRuntimeExports.jsx(TeX,{children:"("+element.options.coordX+", "+element.options.coordY+")"})," — ",jsxRuntimeExports.jsx(TeX,{children:element.options.width+" \\times "+element.options.height})]}),onUp:n===0?null:()=>this._moveElementUp(n),onDown:n===this.props.elements.length-1?null:()=>this._moveElementDown(n),onDelete:()=>this._deleteElement(n),children:jsxRuntimeExports.jsx(RectangleEditor,{...element.options,onChange:newProps=>{const elements=JSON.parse(JSON.stringify(this.props.elements));Object.assign(elements[n].options,newProps);this.props.onChange({elements:elements});}})},element.key)}}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-interaction-editor-select-element",children:jsxRuntimeExports.jsxs("select",{onChange:this._addNewElement,children:[jsxRuntimeExports.jsxs("option",{value:"",children:["Add an element","…"]}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"point",children:"Point"}),jsxRuntimeExports.jsx("option",{value:"line",children:"Line segment"}),jsxRuntimeExports.jsx("option",{value:"function",children:"Function plot"}),jsxRuntimeExports.jsx("option",{value:"parametric",children:"Parametric plot"}),jsxRuntimeExports.jsx("option",{value:"label",children:"Label"}),jsxRuntimeExports.jsx("option",{value:"rectangle",children:"Rectangle"}),jsxRuntimeExports.jsx("option",{value:"movable-point",children:"★ Movable point"}),jsxRuntimeExports.jsx("option",{value:"movable-line",children:"★ Movable line segment"})]})})]})}constructor(...args){super(...args),this.state={usedVarSubscripts:this._getAllVarSubscripts(this.props.elements),usedFunctionNames:this._getAllFunctionNames(this.props.elements)},this._updateGraphProps=newProps=>{const{step,...rest}=newProps;this.props.onChange({graph:{...this.props.graph,...rest,tickStep:step}});},this._addNewElement=e=>{const elementType=e.target.value;if(elementType===""){return}e.target.value="";const newElement={type:elementType,key:elementType+"-"+(Math.random()*0xffffff<<0).toString(16),options:{...defaultOptionsByElementType[elementType]}};let nextSubscript;if(elementType==="movable-point"){nextSubscript=Math.max(...this.state.usedVarSubscripts,-1)+1;newElement.options.varSubscript=nextSubscript;}else if(elementType==="movable-line"){nextSubscript=Math.max(...this.state.usedVarSubscripts,-1)+1;newElement.options.startSubscript=nextSubscript;newElement.options.endSubscript=nextSubscript+1;}else if(elementType==="function"){const nextLetter=String.fromCharCode(Math.max(...this.state.usedFunctionNames.map(c=>c.charCodeAt(0)),"e".charCodeAt(0))+1);newElement.options.funcName=nextLetter;}this.props.onChange({elements:this.props.elements.concat(newElement)});},this._deleteElement=index=>{const element=this.props.elements[index];this.props.onChange({elements:this.props.elements.filter(e=>e!==element)});},this._moveElementUp=index=>{const element=this.props.elements[index];const newElements=this.props.elements.filter(e=>e!==element);newElements.splice(index-1,0,element);this.props.onChange({elements:newElements});},this._moveElementDown=index=>{const element=this.props.elements[index];const newElements=this.props.elements.filter(e=>e!==element);newElements.splice(index+1,0,element);this.props.onChange({elements:newElements});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}InteractionEditor.defaultProps=interactionLogic.defaultWidgetOptions;
1649
1650
 
1650
- var styles$F = {"singleSelectShort":"perseus_wAZzFxEx","row":"perseus_6FquBkGo"};
1651
+ var styles$E = {"singleSelectShort":"perseus_wAZzFxEx","row":"perseus_6FquBkGo"};
1651
1652
 
1652
- const LabeledRow=props=>{const{children,label,labelSide="left",labelSize="small",style}=props;return jsxRuntimeExports.jsx("label",{className:css(styles$E.label),children:jsxRuntimeExports.jsxs(View,{style:[styles$E.row,style],children:[labelSide==="start"||jsxRuntimeExports.jsx(BodyText,{size:labelSize==="small"?"small":undefined,tag:"span",style:styles$E.spaceEnd,children:label}),children,labelSide==="end"&&jsxRuntimeExports.jsx(BodyText,{size:labelSize==="small"?"small":undefined,tag:"span",style:styles$E.spaceStart,children:label})]})})};const styles$E=StyleSheet.create({label:{width:"fit-content"},row:{flexDirection:"row",marginBlockStart:spacing.xSmall_8,alignItems:"center",width:"fit-content"},spaceStart:{marginInlineStart:spacing.xSmall_8},spaceEnd:{marginInlineEnd:spacing.xSmall_8}});
1653
+ const LabeledRow=props=>{const{children,label,labelSide="left",labelSize="small",style}=props;return jsxRuntimeExports.jsx("label",{className:css(styles$D.label),children:jsxRuntimeExports.jsxs(View,{style:[styles$D.row,style],children:[labelSide==="start"||jsxRuntimeExports.jsx(BodyText,{size:labelSize==="small"?"small":undefined,tag:"span",style:styles$D.spaceEnd,children:label}),children,labelSide==="end"&&jsxRuntimeExports.jsx(BodyText,{size:labelSize==="small"?"small":undefined,tag:"span",style:styles$D.spaceStart,children:label})]})})};const styles$D=StyleSheet.create({label:{width:"fit-content"},row:{flexDirection:"row",marginBlockStart:spacing.xSmall_8,alignItems:"center",width:"fit-content"},spaceStart:{marginInlineStart:spacing.xSmall_8},spaceEnd:{marginInlineEnd:spacing.xSmall_8}});
1653
1654
 
1654
- function AngleAnswerOptions({correct,graph,onChange}){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$F.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Show angle measures"}),checked:!!correct?.showAngles,onChange:newValue=>{if(graph?.type==="angle"){invariant(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);onChange({correct:{...correct,showAngles:newValue},graph:{...graph,showAngles:newValue}});}}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{className:styles$F.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Allow reflex angles"}),checked:!!correct?.allowReflexAngles,onChange:newValue=>{invariant(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);invariant(graph?.type==="angle",`Expected graph type to be angle, but got ${graph?.type}`);const update={allowReflexAngles:newValue};onChange({correct:{...correct,...update},graph:{...graph,...update}});}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Allow students to be able to create reflex angles."})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.match||"exact",options:{exact:"match exactly",congruent:"be congruent"},onChange:newValue=>{const match=newValue==="exact"?undefined:newValue;onChange({correct:{...correct,match}});},className:styles$F.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{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."})})]})]})}
1655
+ function AngleAnswerOptions({correct,graph,onChange}){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$E.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Show angle measures"}),checked:!!correct?.showAngles,onChange:newValue=>{if(graph?.type==="angle"){invariant(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);onChange({correct:{...correct,showAngles:newValue},graph:{...graph,showAngles:newValue}});}}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{className:styles$E.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Allow reflex angles"}),checked:!!correct?.allowReflexAngles,onChange:newValue=>{invariant(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);invariant(graph?.type==="angle",`Expected graph type to be angle, but got ${graph?.type}`);const update={allowReflexAngles:newValue};onChange({correct:{...correct,...update},graph:{...graph,...update}});}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Allow students to be able to create reflex angles."})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.match||"exact",options:{exact:"match exactly",congruent:"be congruent"},onChange:newValue=>{const match=newValue==="exact"?undefined:newValue;onChange({correct:{...correct,match}});},className:styles$E.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{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."})})]})]})}
1655
1656
 
1656
1657
  const UNLIMITED="unlimited";const parsePointCount=points=>{const parsed=parseInt(points,10);if(isNaN(parsed)){return UNLIMITED}return parsed===0?UNLIMITED:parsed};
1657
1658
 
1658
- const pointsCountOptions={"1":"1 point","2":"2 points","3":"3 points","4":"4 points","5":"5 points","6":"6 points",[UNLIMITED]:"unlimited"};const GraphPointsCountSelector=({correct,graph,onChange})=>{return jsxRuntimeExports.jsx(LabeledRow,{label:"Number of Points:",children:jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:`${correct.numPoints??1}`,options:pointsCountOptions,onChange:newValue=>{const points=parsePointCount(newValue);onChange({correct:{type:"point",numPoints:points},graph:{type:"point",numPoints:points}});},className:styles$F.singleSelectShort})})};
1659
+ const pointsCountOptions={"1":"1 point","2":"2 points","3":"3 points","4":"4 points","5":"5 points","6":"6 points",[UNLIMITED]:"unlimited"};const GraphPointsCountSelector=({correct,graph,onChange})=>{return jsxRuntimeExports.jsx(LabeledRow,{label:"Number of Points:",children:jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:`${correct.numPoints??1}`,options:pointsCountOptions,onChange:newValue=>{const points=parsePointCount(newValue);onChange({correct:{type:"point",numPoints:points},graph:{type:"point",numPoints:points}});},className:styles$E.singleSelectShort})})};
1659
1660
 
1660
- const GraphTypeSelector=props=>{return jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:props.graphType,onChange:props.onChange,placeholder:"Select an answer type",className:styles$F.singleSelectShort,disabled:props.disabled,options:{none:"None","absolute-value":"Absolute value function",exponential:"Exponential function",linear:"Linear function",logarithm:"Logarithmic function",quadratic:"Quadratic function",sinusoid:"Sinusoidal function",tangent:"Tangent function",angle:"Angle",circle:"Circle","linear-system":"Linear system",segment:"Line segment(s)",point:"Point(s)",polygon:"Polygon",ray:"Ray",vector:"Vector"}})};
1661
+ const GraphTypeSelector=props=>{return jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:props.graphType,onChange:props.onChange,placeholder:"Select an answer type",className:styles$E.singleSelectShort,disabled:props.disabled,options:{none:"None","absolute-value":"Absolute value function",exponential:"Exponential function",linear:"Linear function",logarithm:"Logarithmic function",quadratic:"Quadratic function",sinusoid:"Sinusoidal function",tangent:"Tangent function",angle:"Angle",circle:"Circle","linear-system":"Linear system",segment:"Line segment(s)",point:"Point(s)",polygon:"Polygon",ray:"Ray",vector:"Vector"}})};
1661
1662
 
1662
1663
  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(BodyText,{size:"xsmall",style:{paddingBlockStart:spacing.xxSmall_6,paddingBlockEnd:spacing.xxSmall_6,color:semanticColor.core.foreground.neutral.subtle},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]})]})}
1663
1664
 
1664
- var styles$D = {"container":"perseus_7paQgL4U","caption":"perseus_DdFGH-ag"};
1665
+ var styles$C = {"container":"perseus_7paQgL4U","caption":"perseus_DdFGH-ag"};
1665
1666
 
1666
- function InteractiveGraphDescription(props){const{ariaLabelValue,ariaDescriptionValue,editingDisabled=false,onChange}=props;const[isOpen,setIsOpen]=React.useState(true);const uniqueId=React.useId();const descriptionTextAreaId=`${uniqueId}-description-textarea`;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Description",isCollapsible:true,isOpen:isOpen,onToggle:setIsOpen}),isOpen&&jsxRuntimeExports.jsxs(View,{className:styles$D.container,children:[jsxRuntimeExports.jsx(BodyText,{size:"xsmall",className:styles$D.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.jsx(BodyText,{size:"xsmall",className:styles$D.caption,children:"Aria description required when using locked figures. Locked figures aren't automatically described."}),jsxRuntimeExports.jsxs(BodyText,{size:"medium",weight:"bold",tag:"label",children:["Title",jsxRuntimeExports.jsx(TextField,{value:ariaLabelValue,onChange:newValue=>onChange({fullGraphAriaLabel:newValue||undefined}),disabled:editingDisabled,style:{marginBlockStart:sizing.size_040}})]}),jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"label",htmlFor:descriptionTextAreaId,children:"Description"}),jsxRuntimeExports.jsx(TextArea,{id:descriptionTextAreaId,value:ariaDescriptionValue,onChange:newValue=>onChange({fullGraphAriaDescription:newValue||undefined}),disabled:editingDisabled,autoResize:true})]})]})}
1667
+ function InteractiveGraphDescription(props){const{ariaLabelValue,ariaDescriptionValue,editingDisabled=false,onChange}=props;const[isOpen,setIsOpen]=React.useState(true);const uniqueId=React.useId();const descriptionTextAreaId=`${uniqueId}-description-textarea`;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Description",isCollapsible:true,isOpen:isOpen,onToggle:setIsOpen}),isOpen&&jsxRuntimeExports.jsxs(View,{className:styles$C.container,children:[jsxRuntimeExports.jsx(BodyText,{size:"xsmall",className:styles$C.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.jsx(BodyText,{size:"xsmall",className:styles$C.caption,children:"Aria description required when using locked figures. Locked figures aren't automatically described."}),jsxRuntimeExports.jsxs(BodyText,{size:"medium",weight:"bold",tag:"label",children:["Title",jsxRuntimeExports.jsx(TextField,{value:ariaLabelValue,onChange:newValue=>onChange({fullGraphAriaLabel:newValue||undefined}),disabled:editingDisabled,style:{marginBlockStart:sizing.size_040}})]}),jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"label",htmlFor:descriptionTextAreaId,children:"Description"}),jsxRuntimeExports.jsx(TextArea,{id:descriptionTextAreaId,value:ariaDescriptionValue,onChange:newValue=>onChange({fullGraphAriaDescription:newValue||undefined}),disabled:editingDisabled,autoResize:true})]})]})}
1667
1668
 
1668
1669
  function AxisArrowSwitches(props){const{showAxisArrows,onChange,disabled}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(BodyText,{size:"small",children:"Arrows"}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",style:{display:"flex",flexDirection:"row",alignItems:"center",gap:sizing.size_060},children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"x min",labelSide:"start",size:"small",checked:showAxisArrows.xMin,disabled:disabled,onChange:()=>onChange("xMin")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"y min",labelSide:"start",size:"small",checked:showAxisArrows.yMin,disabled:disabled,onChange:()=>onChange("yMin")})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",style:{display:"flex",flexDirection:"row",alignItems:"center",gap:sizing.size_060},children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"x max",labelSide:"start",size:"small",checked:showAxisArrows.xMax,disabled:disabled,onChange:()=>onChange("xMax")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"y max",labelSide:"start",size:"small",checked:showAxisArrows.yMax,disabled:disabled,onChange:()=>onChange("yMax")})})]})]})}
1669
1670
 
1670
1671
  function AxisTickSwitches(props){const{showAxisTicks,onChange,disabled}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(BodyText,{size:"small",children:"Ticks"}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",style:{display:"flex",flexDirection:"row",alignItems:"center",gap:sizing.size_060},children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"x-axis",labelSide:"start",size:"small",checked:showAxisTicks.x,disabled:disabled,onChange:()=>onChange("x")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"y-axis",labelSide:"start",size:"small",checked:showAxisTicks.y,disabled:disabled,onChange:()=>onChange("y")})})]})]})}
1671
1672
 
1672
- var styles$C = {"backgroundUrlInput":"perseus_so0nIc4z","checkboxRow":"perseus_lfG1X93S","protractorSection":"perseus_thf-SEbO"};
1673
+ var styles$B = {"backgroundUrlInput":"perseus_so0nIc4z","checkboxRow":"perseus_lfG1X93S","protractorSection":"perseus_thf-SEbO"};
1673
1674
 
1674
- const{ButtonGroup: ButtonGroup$1,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,showAxisArrowsSwitches:props.showAxisArrows,showAxisTicksSwitches:props.showAxisTicks,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(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;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"),disabled:editingDisabled})})}),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.jsx(AxisArrowSwitches,{showAxisArrows:this.state.showAxisArrowsSwitches,onChange:this.changeShowAxisArrows,disabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsx(AxisTickSwitches,{showAxisTicks:this.state.showAxisTicksSwitches,onChange:this.changeShowAxisTicks,disabled:this.props.apiOptions?.editingDisabled??false}),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();},disabled:editingDisabled,children:"Auto-adjust steps"}),jsxRuntimeExports.jsxs(InfoTip,{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"),disabled:editingDisabled})})}),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});},disabled:editingDisabled})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Background image URL",style:{marginBlockStart:0},children:[jsxRuntimeExports.jsx("input",{type:"text",className:styles$C.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,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),jsxRuntimeExports.jsxs(View,{className:styles$C.protractorSection,children:[jsxRuntimeExports.jsx(View,{className:styles$C.checkboxRow,children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.change({showProtractor:value});},disabled:editingDisabled,style:{marginBlockStart:0}})}),this.props.showProtractor&&jsxRuntimeExports.jsx(Banner,{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 deprecatedChangeableChange.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.changeShowAxisArrows=axis=>{const newShowAxisArrows={...this.state.showAxisArrowsSwitches};newShowAxisArrows[axis]=!newShowAxisArrows[axis];this.setState({showAxisArrowsSwitches:newShowAxisArrows},this.changeGraph);},this.changeShowAxisTicks=axis=>{const newShowAxisTicks={...this.state.showAxisTicksSwitches};newShowAxisTicks[axis]=!newShowAxisTicks[axis];this.setState({showAxisTicksSwitches:newShowAxisTicks},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:gridStep.map(function(step){return step/2})},this.changeGraph);},this.changeGraph=()=>{const labels=this.state.labelsTextbox;const labelLocation=this.state.labelLocation;const range=this.state.rangeTextbox.map(range=>range.map(value=>Number(value)));const showAxisArrows=this.state.showAxisArrowsSwitches;const showAxisTicks=this.state.showAxisTicksSwitches;const step=this.state.stepTextbox.map(value=>Number(value));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,showAxisArrows:showAxisArrows,showAxisTicks:showAxisTicks,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,showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true}};
1675
+ const{ButtonGroup: ButtonGroup$1,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,showAxisArrowsSwitches:props.showAxisArrows,showAxisTicksSwitches:props.showAxisTicks,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(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;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"),disabled:editingDisabled})})}),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.jsx(AxisArrowSwitches,{showAxisArrows:this.state.showAxisArrowsSwitches,onChange:this.changeShowAxisArrows,disabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsx(AxisTickSwitches,{showAxisTicks:this.state.showAxisTicksSwitches,onChange:this.changeShowAxisTicks,disabled:this.props.apiOptions?.editingDisabled??false}),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();},disabled:editingDisabled,children:"Auto-adjust steps"}),jsxRuntimeExports.jsxs(InfoTip,{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"),disabled:editingDisabled})})}),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});},disabled:editingDisabled})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Background image URL",style:{marginBlockStart:0},children:[jsxRuntimeExports.jsx("input",{type:"text",className:styles$B.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,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),jsxRuntimeExports.jsxs(View,{className:styles$B.protractorSection,children:[jsxRuntimeExports.jsx(View,{className:styles$B.checkboxRow,children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.change({showProtractor:value});},disabled:editingDisabled,style:{marginBlockStart:0}})}),this.props.showProtractor&&jsxRuntimeExports.jsx(Banner,{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 deprecatedChangeableChange.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.changeShowAxisArrows=axis=>{const newShowAxisArrows={...this.state.showAxisArrowsSwitches};newShowAxisArrows[axis]=!newShowAxisArrows[axis];this.setState({showAxisArrowsSwitches:newShowAxisArrows},this.changeGraph);},this.changeShowAxisTicks=axis=>{const newShowAxisTicks={...this.state.showAxisTicksSwitches};newShowAxisTicks[axis]=!newShowAxisTicks[axis];this.setState({showAxisTicksSwitches:newShowAxisTicks},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:gridStep.map(function(step){return step/2})},this.changeGraph);},this.changeGraph=()=>{const labels=this.state.labelsTextbox;const labelLocation=this.state.labelLocation;const range=this.state.rangeTextbox.map(range=>range.map(value=>Number(value)));const showAxisArrows=this.state.showAxisArrowsSwitches;const showAxisTicks=this.state.showAxisTicksSwitches;const step=this.state.stepTextbox.map(value=>Number(value));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,showAxisArrows:showAxisArrows,showAxisTicks:showAxisTicks,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,showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true}};
1675
1676
 
1676
- var styles$B = {"treeList":"perseus_dM32KBSs","indentList":"perseus_0LO0xYxg","switchRow":"perseus_T8Wphznm"};
1677
+ var styles$A = {"treeList":"perseus_dM32KBSs","indentList":"perseus_0LO0xYxg","switchRow":"perseus_T8Wphznm"};
1677
1678
 
1678
- const badgeSpacingStyle={marginInlineEnd:sizing.size_060};const badgeLabelStyle={fontWeight:font.weight.regular};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",{className:styles$B.treeList,children:elementArias.map((aria,index)=>jsxRuntimeExports.jsxs("li",{children:[showTags&&jsxRuntimeExports.jsx(StatusBadge,{kind:"success",label:aria.roleOrTag,showBorder:false,styles:{root:badgeSpacingStyle,label:badgeLabelStyle}}),aria.className,jsxRuntimeExports.jsx("ul",{className:styles$B.indentList,children:aria.attributes.map((value,index)=>jsxRuntimeExports.jsxs("li",{children:[value.name==="label"?jsxRuntimeExports.jsx(StatusBadge,{kind:"info",label:value.name,showBorder:false,styles:{root:badgeSpacingStyle,label:badgeLabelStyle}}):jsxRuntimeExports.jsx(NeutralBadge,{label:value.name,showBorder:false,styles:{root:badgeSpacingStyle,label:badgeLabelStyle}}),value.value]},index))})]},index))})}function InteractiveGraphSRTree({graphId,correct,fullGraphAriaLabel,fullGraphAriaDescription,lockedFigures,editingDisabled=false}){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,{className:styles$B.switchRow,children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:showTags,onChange:setShowTags,disabled:editingDisabled}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"label",htmlFor:switchId,children:"Show HTML roles/tags"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsx(InfoTip,{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})]})]})}
1679
+ const badgeSpacingStyle={marginInlineEnd:sizing.size_060};const badgeLabelStyle={fontWeight:font.weight.regular};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",{className:styles$A.treeList,children:elementArias.map((aria,index)=>jsxRuntimeExports.jsxs("li",{children:[showTags&&jsxRuntimeExports.jsx(StatusBadge,{kind:"success",label:aria.roleOrTag,showBorder:false,styles:{root:badgeSpacingStyle,label:badgeLabelStyle}}),aria.className,jsxRuntimeExports.jsx("ul",{className:styles$A.indentList,children:aria.attributes.map((value,index)=>jsxRuntimeExports.jsxs("li",{children:[value.name==="label"?jsxRuntimeExports.jsx(StatusBadge,{kind:"info",label:value.name,showBorder:false,styles:{root:badgeSpacingStyle,label:badgeLabelStyle}}):jsxRuntimeExports.jsx(NeutralBadge,{label:value.name,showBorder:false,styles:{root:badgeSpacingStyle,label:badgeLabelStyle}}),value.value]},index))})]},index))})}function InteractiveGraphSRTree({graphId,correct,fullGraphAriaLabel,fullGraphAriaDescription,lockedFigures,editingDisabled=false}){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,{className:styles$A.switchRow,children:[jsxRuntimeExports.jsx(Switch,{id:switchId,checked:showTags,onChange:setShowTags,disabled:editingDisabled}),jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"label",htmlFor:switchId,children:"Show HTML roles/tags"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsx(InfoTip,{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})]})]})}
1679
1680
 
1680
- const POLYGON_SIDES_OPTIONS={"3":"3 sides","4":"4 sides","5":"5 sides","6":"6 sides","7":"7 sides","8":"8 sides","9":"9 sides","10":"10 sides","11":"11 sides","12":"12 sides",unlimited:"unlimited sides"};function PolygonAnswerOptions({correct,graph,onChange}){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Number of sides:",children:jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct?.numSides?`${correct.numSides}`:"3",options:POLYGON_SIDES_OPTIONS,onChange:newValue=>{invariant(graph?.type==="polygon");const updates={numSides:parsePointCount(newValue),coords:undefined,startCoords:undefined,snapTo:"grid"};onChange({correct:{...correct,...updates},graph:{...graph,...updates}});},className:styles$F.singleSelectShort},"polygon-select")}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Snap to:",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.snapTo||"grid",options:{grid:"grid",angles:correct.numSides!=="unlimited"&&"interior angles",sides:correct.numSides!=="unlimited"&&"side measures"},onChange:newValue=>{invariant(graph?.type==="polygon",`Expected graph type to be polygon, but got ${graph?.type}`);const updates={snapTo:newValue,coords:null};onChange({correct:{...correct,...updates},graph:{...graph,...updates}});},className:styles$F.singleSelectShort}),jsxRuntimeExports.jsxs(InfoTip,{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,{className:styles$F.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Show angle measures"}),checked:!!correct?.showAngles,onChange:()=>{if(graph?.type==="polygon"){invariant(correct.type==="polygon",`Expected graph type to be polygon, but got ${correct.type}`);onChange({correct:{...correct,showAngles:!correct.showAngles},graph:{...graph,showAngles:!graph.showAngles}});}}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{className:styles$F.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Show side measures"}),checked:!!correct?.showSides,onChange:()=>{if(graph?.type==="polygon"&&correct.type==="polygon"){onChange({correct:{...correct,showSides:!correct.showSides},graph:{...graph,showSides:!graph.showSides}});}}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Displays the side lengths."})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.match||"exact",onChange:match=>{onChange({correct:{...correct,match}});},options:{exact:"match exactly",congruent:"be congruent",approx:"be approximately congruent",similar:"be similar"},className:styles$F.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{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."]})})]})})]})]})}
1681
+ const POLYGON_SIDES_OPTIONS={"3":"3 sides","4":"4 sides","5":"5 sides","6":"6 sides","7":"7 sides","8":"8 sides","9":"9 sides","10":"10 sides","11":"11 sides","12":"12 sides",unlimited:"unlimited sides"};function PolygonAnswerOptions({correct,graph,onChange}){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Number of sides:",children:jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct?.numSides?`${correct.numSides}`:"3",options:POLYGON_SIDES_OPTIONS,onChange:newValue=>{invariant(graph?.type==="polygon");const updates={numSides:parsePointCount(newValue),coords:undefined,startCoords:undefined,snapTo:"grid"};onChange({correct:{...correct,...updates},graph:{...graph,...updates}});},className:styles$E.singleSelectShort},"polygon-select")}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Snap to:",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.snapTo||"grid",options:{grid:"grid",angles:correct.numSides!=="unlimited"&&"interior angles",sides:correct.numSides!=="unlimited"&&"side measures"},onChange:newValue=>{invariant(graph?.type==="polygon",`Expected graph type to be polygon, but got ${graph?.type}`);const updates={snapTo:newValue,coords:null};onChange({correct:{...correct,...updates},graph:{...graph,...updates}});},className:styles$E.singleSelectShort}),jsxRuntimeExports.jsxs(InfoTip,{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,{className:styles$E.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Show angle measures"}),checked:!!correct?.showAngles,onChange:()=>{if(graph?.type==="polygon"){invariant(correct.type==="polygon",`Expected graph type to be polygon, but got ${correct.type}`);onChange({correct:{...correct,showAngles:!correct.showAngles},graph:{...graph,showAngles:!graph.showAngles}});}}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(View,{className:styles$E.row,children:[jsxRuntimeExports.jsx(Checkbox$1,{label:jsxRuntimeExports.jsx(BodyText,{size:"small",tag:"span",children:"Show side measures"}),checked:!!correct?.showSides,onChange:()=>{if(graph?.type==="polygon"&&correct.type==="polygon"){onChange({correct:{...correct,showSides:!correct.showSides},graph:{...graph,showSides:!graph.showSides}});}}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Displays the side lengths."})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.match||"exact",onChange:match=>{onChange({correct:{...correct,match}});},options:{exact:"match exactly",congruent:"be congruent",approx:"be approximately congruent",similar:"be similar"},className:styles$E.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{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."]})})]})})]})]})}
1681
1682
 
1682
- const segmentCountOptions={"1":"1 segment","2":"2 segments","3":"3 segments","4":"4 segments","5":"5 segments","6":"6 segments"};const SegmentCountSelector=({correct,graph,onChange})=>jsxRuntimeExports.jsx(LabeledRow,{label:"Number of segments:",children:jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:`${correct.numSegments??1}`,options:segmentCountOptions,onChange:newValue=>{const sides=+newValue;onChange({correct:{type:"segment",numSegments:sides,coords:null},graph:{type:"segment",numSegments:sides}});},className:styles$F.singleSelectShort},"segment-select")});
1683
+ const segmentCountOptions={"1":"1 segment","2":"2 segments","3":"3 segments","4":"4 segments","5":"5 segments","6":"6 segments"};const SegmentCountSelector=({correct,graph,onChange})=>jsxRuntimeExports.jsx(LabeledRow,{label:"Number of segments:",children:jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:`${correct.numSegments??1}`,options:segmentCountOptions,onChange:newValue=>{const sides=+newValue;onChange({correct:{type:"segment",numSegments:sides,coords:null},graph:{type:"segment",numSegments:sides}});},className:styles$E.singleSelectShort},"segment-select")});
1683
1684
 
1684
- var styles$A = {"switchRow":"perseus_FCU7fslB"};
1685
+ var styles$z = {"switchRow":"perseus_FCU7fslB"};
1685
1686
 
1686
- function ShowPointLabelsToggle({showPointLabels,pointLabels,onChange}){const hasAtLeastOneLabel=pointLabels!==undefined&&pointLabels.some(label=>label!=="");return jsxRuntimeExports.jsxs(View,{className:styles$A.switchRow,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Show point labels",checked:hasAtLeastOneLabel&&showPointLabels,disabled:!hasAtLeastOneLabel,onChange:onChange}),jsxRuntimeExports.jsx(InfoTip,{children:"When on, each labeled movable point displays a visible label next to it. Add a label to at least one point below to enable this option; unlabeled points render without a label."})]})}
1687
+ function ShowPointLabelsToggle({showPointLabels,pointLabels,onChange}){const hasAtLeastOneLabel=pointLabels!==undefined&&pointLabels.some(label=>label!=="");return jsxRuntimeExports.jsxs(View,{className:styles$z.switchRow,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Show point labels",checked:hasAtLeastOneLabel&&showPointLabels,disabled:!hasAtLeastOneLabel,onChange:onChange}),jsxRuntimeExports.jsx(InfoTip,{children:"When on, each labeled movable point displays a visible label next to it. Add a label to at least one point below to enable this option; unlabeled points render without a label."})]})}
1687
1688
 
1688
- function VectorAnswerOptions({correct,onChange}){return jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.match||"exact",onChange:match=>{onChange({correct:{...correct,match}});},options:{exact:"match exactly",congruent:"be congruent"},className:styles$F.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Congruency requires only that the vector has the same direction and magnitude. An exact match implies congruency, but also requires that the tail and tip are in the same position on the grid."})})]})}
1689
+ function VectorAnswerOptions({correct,onChange}){return jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:correct.match||"exact",onChange:match=>{onChange({correct:{...correct,match}});},options:{exact:"match exactly",congruent:"be congruent"},className:styles$E.singleSelectShort}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Congruency requires only that the vector has the same direction and magnitude. An exact match implies congruency, but also requires that the tail and tip are in the same position on the grid."})})]})}
1689
1690
 
1690
- var styles$z = {"container":"perseus_UMms5ska","addElementSelect":"perseus_Dz9XA5LM"};
1691
+ var styles$y = {"container":"perseus_UMms5ska","addElementSelect":"perseus_Dz9XA5LM"};
1691
1692
 
1692
- const LockedFigureSelect=props=>{const{id,editingDisabled,onChange}=props;const figureTypes=["point","line","vector","ellipse","polygon","function","label"];return jsxRuntimeExports.jsx(View,{className:styles$z.container,children:jsxRuntimeExports.jsx(ActionMenu,{menuText:"Add locked figure",disabled:editingDisabled,className:styles$z.addElementSelect,children:figureTypes.map(figureType=>jsxRuntimeExports.jsx(ActionItem,{label:figureType,onClick:()=>onChange(figureType)},`${id}-${figureType}`))})})};
1693
+ const LockedFigureSelect=props=>{const{id,editingDisabled,onChange}=props;const figureTypes=["point","line","vector","ellipse","polygon","function","label"];return jsxRuntimeExports.jsx(View,{className:styles$y.container,children:jsxRuntimeExports.jsx(ActionMenu,{menuText:"Add locked figure",disabled:editingDisabled,className:styles$y.addElementSelect,children:figureTypes.map(figureType=>jsxRuntimeExports.jsx(ActionItem,{label:figureType,onClick:()=>onChange(figureType)},`${id}-${figureType}`))})})};
1693
1694
 
1694
- 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(BodyText,{tag:"label",style:styles$y.row,children:["angle (degrees)",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:angleInput,onChange:handleAngleChange,style:styles$y.textField}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6})]})};const styles$y=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1695
+ 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(BodyText,{tag:"label",style:styles$x.row,children:["angle (degrees)",jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:angleInput,onChange:handleAngleChange,style:styles$x.textField}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6})]})};const styles$x=StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1695
1696
 
1696
- var styles$x = {"container":"perseus_6kPoH3-I","label":"perseus_qYirPY7G"};
1697
+ var styles$w = {"container":"perseus_6kPoH3-I","label":"perseus_qYirPY7G"};
1697
1698
 
1698
- const textFieldStyle={width:sizing.size_640};const errorFieldStyle={borderColor:semanticColor.core.border.critical.default,backgroundColor:semanticColor.core.background.critical.subtle};const CoordinatePairInput=props=>{const{coord,labels,error,style,labelClassName,disabled=false,onChange}=props;const xLabel=labels?labels[0]:"x coord";const yLabel=labels?labels[1]:"y coord";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,{className:styles$x.container,style:style,children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$x.label,children:[jsxRuntimeExports.jsx("span",{className:labelClassName,children:xLabel}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[0],disabled:disabled,onChange:newValue=>handleCoordChange(newValue,0),style:[textFieldStyle,error?errorFieldStyle:undefined]})]}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$x.label,children:[jsxRuntimeExports.jsx("span",{className:labelClassName,children:yLabel}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[1],disabled:disabled,onChange:newValue=>handleCoordChange(newValue,1),style:[textFieldStyle,error?errorFieldStyle:undefined]})]})]})};
1699
+ const textFieldStyle={width:sizing.size_640};const errorFieldStyle={borderColor:semanticColor.core.border.critical.default,backgroundColor:semanticColor.core.background.critical.subtle};const CoordinatePairInput=props=>{const{coord,labels,error,style,labelClassName,disabled=false,onChange}=props;const xLabel=labels?labels[0]:"x coord";const yLabel=labels?labels[1]:"y coord";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,{className:styles$w.container,style:style,children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$w.label,children:[jsxRuntimeExports.jsx("span",{className:labelClassName,children:xLabel}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[0],disabled:disabled,onChange:newValue=>handleCoordChange(newValue,0),style:[textFieldStyle,error?errorFieldStyle:undefined]})]}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$w.label,children:[jsxRuntimeExports.jsx("span",{className:labelClassName,children:yLabel}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:coordState[1],disabled:disabled,onChange:newValue=>handleCoordChange(newValue,1),style:[textFieldStyle,error?errorFieldStyle:undefined]})]})]})};
1699
1700
 
1700
- var styles$w = {"row":"perseus_v9IBfM--"};
1701
+ var styles$v = {"row":"perseus_v9IBfM--"};
1701
1702
 
1702
- const ColorSwatch=props=>{const{color,filled=true,decorative=false}=props;return jsxRuntimeExports.jsx(View,{"aria-label":!decorative?`${color}, ${filled?"filled":"open"}`:undefined,style:[styles$v.colorSwatch,{border:`4px solid ${lockedFigureColors[color]}`,backgroundColor:filled?lockedFigureColors[color]:semanticColor.core.background.base.default}]})};const styles$v=StyleSheet.create({colorSwatch:{outline:`2px solid ${semanticColor.focus.inner}`,borderRadius:"50%",width:spacing.large_24,height:spacing.large_24}});
1703
+ const ColorSwatch=props=>{const{color,filled=true,decorative=false}=props;return jsxRuntimeExports.jsx(View,{"aria-label":!decorative?`${color}, ${filled?"filled":"open"}`:undefined,style:[styles$u.colorSwatch,{border:`4px solid ${lockedFigureColors[color]}`,backgroundColor:filled?lockedFigureColors[color]:semanticColor.core.background.base.default}]})};const styles$u=StyleSheet.create({colorSwatch:{outline:`2px solid ${semanticColor.focus.inner}`,borderRadius:"50%",width:spacing.large_24,height:spacing.large_24}});
1703
1704
 
1704
- const ColorSelect=props=>{const{selectedValue,style,editingDisabled=false,onChange}=props;function option(color){return {label:color,leftAccessory:jsxRuntimeExports.jsx(ColorSwatch,{color:color,decorative:true})}}return jsxRuntimeExports.jsx(View,{className:styles$w.row,style:style,children:jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$w.row,children:["color",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:selectedValue,disabled:editingDisabled,onChange:onChange,options:{blue:option("blue"),gold:option("gold"),green:option("green"),grayH:option("grayH"),purple:option("purple"),pink:option("pink"),red:option("red")}})]})})};
1705
+ const ColorSelect=props=>{const{selectedValue,style,editingDisabled=false,onChange}=props;function option(color){return {label:color,leftAccessory:jsxRuntimeExports.jsx(ColorSwatch,{color:color,decorative:true})}}return jsxRuntimeExports.jsx(View,{className:styles$v.row,style:style,children:jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$v.row,children:["color",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:selectedValue,disabled:editingDisabled,onChange:onChange,options:{blue:option("blue"),gold:option("gold"),green:option("green"),grayH:option("grayH"),purple:option("purple"),pink:option("pink"),red:option("red")}})]})})};
1705
1706
 
1706
- const EllipseSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$u.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$u.innerCircle,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$u=StyleSheet.create({container:{outline:`2px solid ${semanticColor.focus.inner}`,borderRadius:"50%",width:spacing.xLarge_32,height:spacing.large_24,backgroundColor:semanticColor.core.background.base.default,alignItems:"center",justifyContent:"center"},innerCircle:{width:28,height:20,borderRadius:"50%"}});
1707
+ const EllipseSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$t.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$t.innerCircle,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$t=StyleSheet.create({container:{outline:`2px solid ${semanticColor.focus.inner}`,borderRadius:"50%",width:spacing.xLarge_32,height:spacing.large_24,backgroundColor:semanticColor.core.background.base.default,alignItems:"center",justifyContent:"center"},innerCircle:{width:28,height:20,borderRadius:"50%"}});
1707
1708
 
1708
- var styles$t = {"lineStrokeSelect":"perseus_L42pujHE"};
1709
+ var styles$s = {"lineStrokeSelect":"perseus_L42pujHE"};
1709
1710
 
1710
- const lineStrokeStyleOptions={solid:"solid",dashed:"dashed"};const fillableStrokeStyleOptions={solid:"solid",dashed:"dashed",none:"none"};const LineStrokeSelect=props=>{const{selectedValue,options,containerStyle,editingDisabled=false,onChange}=props;return jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$t.lineStrokeSelect,style:containerStyle,children:["stroke",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:selectedValue,disabled:editingDisabled,onChange:onChange,options:options})]})};
1711
+ const lineStrokeStyleOptions={solid:"solid",dashed:"dashed"};const fillableStrokeStyleOptions={solid:"solid",dashed:"dashed",none:"none"};const LineStrokeSelect=props=>{const{selectedValue,options,containerStyle,editingDisabled=false,onChange}=props;return jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$s.lineStrokeSelect,style:containerStyle,children:["stroke",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:selectedValue,disabled:editingDisabled,onChange:onChange,options:options})]})};
1711
1712
 
1712
- var styles$s = {"lineWeightSelect":"perseus_NDL3xmfp"};
1713
+ var styles$r = {"lineWeightSelect":"perseus_NDL3xmfp"};
1713
1714
 
1714
- const LineWeightSelect=props=>{const{selectedValue,containerStyle,editingDisabled=false,onChange}=props;return jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$s.lineWeightSelect,style:containerStyle,children:["weight",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:selectedValue,disabled:editingDisabled,onChange:onChange,options:{thin:"thin",medium:"medium",thick:"thick"}})]})};
1715
+ const LineWeightSelect=props=>{const{selectedValue,containerStyle,editingDisabled=false,onChange}=props;return jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$r.lineWeightSelect,style:containerStyle,children:["weight",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:selectedValue,disabled:editingDisabled,onChange:onChange,options:{thin:"thin",medium:"medium",thick:"thick"}})]})};
1715
1716
 
1716
- var styles$r = {"row":"perseus_mbWJ2QJe","header":"perseus_0eoUQ2Ck","spaceUnder":"perseus_ArAl9ugv","colorRow":"perseus_3tuEF77w","fillLabel":"perseus_mn0Hw09z","truncatedWidth":"perseus_8UEXrB8g","addButton":"perseus_AdQ6tM57","horizontalRule":"perseus_mngqi2xl","sectionTop":"perseus_Nw6aQVGx","dividerTight":"perseus_b5-539TZ"};
1717
+ var styles$q = {"row":"perseus_mbWJ2QJe","header":"perseus_0eoUQ2Ck","spaceUnder":"perseus_ArAl9ugv","colorRow":"perseus_3tuEF77w","fillLabel":"perseus_mn0Hw09z","truncatedWidth":"perseus_8UEXrB8g","addButton":"perseus_AdQ6tM57","horizontalRule":"perseus_mngqi2xl","sectionTop":"perseus_Nw6aQVGx","dividerTight":"perseus_b5-539TZ"};
1717
1718
 
1718
- var styles$q = {"container":"perseus_XtDQYWn5","row":"perseus_B-ZMM2OO","button":"perseus_jRrLESoQ","caption":"perseus_8MnE9qSz"};
1719
+ var styles$p = {"container":"perseus_XtDQYWn5","row":"perseus_B-ZMM2OO","button":"perseus_jRrLESoQ","caption":"perseus_8MnE9qSz"};
1719
1720
 
1720
- function LockedFigureAria(props){const{ariaLabel,getPrepopulatedAriaLabel,editingDisabled=false,onChangeProps}=props;const id=React.useId();const ariaLabelId=`aria-label-${id}`;const[loading,setLoading]=React.useState(false);return jsxRuntimeExports.jsxs(View,{className:styles$q.container,children:[jsxRuntimeExports.jsxs(View,{className:styles$q.row,children:[jsxRuntimeExports.jsx(BodyText,{tag:"label",htmlFor:ariaLabelId,children:"Aria label"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(InfoTip,{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(BodyText,{size:"xsmall",className:styles$q.caption,children:"The figure is hidden from screen readers if this field is left blank."}),jsxRuntimeExports.jsx(TextArea,{id:ariaLabelId,value:loading?"Loading...":ariaLabel??"",disabled:editingDisabled,onChange:newValue=>{onChangeProps({ariaLabel:newValue||undefined});},placeholder:"Ex. Point at (x, y)",rows:1,resizeType:"vertical"}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:pencilCircle,disabled:editingDisabled,className:styles$q.button,onClick:()=>{setLoading(true);getPrepopulatedAriaLabel().then(ariaLabel=>{setLoading(false);onChangeProps({ariaLabel});});},children:"Auto-generate"})]})}
1721
+ function LockedFigureAria(props){const{ariaLabel,getPrepopulatedAriaLabel,editingDisabled=false,onChangeProps}=props;const id=React.useId();const ariaLabelId=`aria-label-${id}`;const[loading,setLoading]=React.useState(false);return jsxRuntimeExports.jsxs(View,{className:styles$p.container,children:[jsxRuntimeExports.jsxs(View,{className:styles$p.row,children:[jsxRuntimeExports.jsx(BodyText,{tag:"label",htmlFor:ariaLabelId,children:"Aria label"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(InfoTip,{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(BodyText,{size:"xsmall",className:styles$p.caption,children:"The figure is hidden from screen readers if this field is left blank."}),jsxRuntimeExports.jsx(TextArea,{id:ariaLabelId,value:loading?"Loading...":ariaLabel??"",disabled:editingDisabled,onChange:newValue=>{onChangeProps({ariaLabel:newValue||undefined});},placeholder:"Ex. Point at (x, y)",rows:1,resizeType:"vertical"}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:pencilCircle,disabled:editingDisabled,className:styles$p.button,onClick:()=>{setLoading(true);getPrepopulatedAriaLabel().then(ariaLabel=>{setLoading(false);onChangeProps({ariaLabel});});},children:"Auto-generate"})]})}
1721
1722
 
1722
- var styles$p = {"container":"perseus_oK9Yeory","deleteButton":"perseus_cNh-Y9Fb"};
1723
+ var styles$o = {"container":"perseus_oK9Yeory","deleteButton":"perseus_cNh-Y9Fb"};
1723
1724
 
1724
- const LockedFigureSettingsActions=props=>{const{figureType,editingDisabled=false,onMove,onRemove}=props;return jsxRuntimeExports.jsxs(View,{className:styles$p.container,children:[jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,"aria-label":`Delete locked ${figureType}`,onClick:onRemove,kind:"tertiary",disabled:editingDisabled,className:styles$p.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`,disabled:editingDisabled,onClick:()=>onMove("back")}),jsxRuntimeExports.jsx(IconButton,{icon:caretUpIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} backward`,disabled:editingDisabled,onClick:()=>onMove("backward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} forward`,disabled:editingDisabled,onClick:()=>onMove("forward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDoubleDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} to the front`,disabled:editingDisabled,onClick:()=>onMove("front")})]})]})};
1725
+ const LockedFigureSettingsActions=props=>{const{figureType,editingDisabled=false,onMove,onRemove}=props;return jsxRuntimeExports.jsxs(View,{className:styles$o.container,children:[jsxRuntimeExports.jsx(Button,{startIcon:trashIcon,"aria-label":`Delete locked ${figureType}`,onClick:onRemove,kind:"tertiary",disabled:editingDisabled,className:styles$o.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`,disabled:editingDisabled,onClick:()=>onMove("back")}),jsxRuntimeExports.jsx(IconButton,{icon:caretUpIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} backward`,disabled:editingDisabled,onClick:()=>onMove("backward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} forward`,disabled:editingDisabled,onClick:()=>onMove("forward")}),jsxRuntimeExports.jsx(IconButton,{icon:caretDoubleDownIcon,kind:"tertiary",size:"small","aria-label":`Move locked ${figureType} to the front`,disabled:editingDisabled,onClick:()=>onMove("front")})]})]})};
1725
1726
 
1726
- var styles$o = {"accordionHeaderContainer":"perseus_WmxZMpCR","accordionHeader":"perseus_ILzLQ6iO","row":"perseus_UalQRyMJ","header":"perseus_b3CfuxCt","textLabel":"perseus_Bj0ezLvT","colorRow":"perseus_FNd80vCz","sizeLabel":"perseus_V-jCdUIK"};
1727
+ var styles$n = {"accordionHeaderContainer":"perseus_WmxZMpCR","accordionHeader":"perseus_ILzLQ6iO","row":"perseus_UalQRyMJ","header":"perseus_b3CfuxCt","textLabel":"perseus_Bj0ezLvT","colorRow":"perseus_FNd80vCz","sizeLabel":"perseus_V-jCdUIK"};
1727
1728
 
1728
- const spaceUnderStyle$3={marginBottom:sizing.size_080};function LockedLabelSettings(props){const{type,coord,color,size,text,expanded,editingDisabled=false,onChangeProps,onMove,onRemove,onToggle,containerStyle}=props;return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{className:`${styles$o.row} ${styles$o.accordionHeaderContainer} ${styles$o.header}`,children:[jsxRuntimeExports.jsxs(BodyText,{size:"medium",weight:"bold",tag:"span",children:["Label (",coord[0],", ",coord[1],")"]}),text!==""&&jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",className:styles$o.accordionHeader,style:{color:lockedFigureColors[color]},children:text})]}),containerStyle:containerStyle,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,disabled:editingDisabled,onChange:newCoords=>{onChangeProps({coord:newCoords});},style:spaceUnderStyle$3}),jsxRuntimeExports.jsxs(View,{className:styles$o.row,children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$o.row} ${styles$o.textLabel}`,children:["text",jsxRuntimeExports.jsx(TextField,{value:text,placeholder:"ex. $x^2$ or $\\frac{1}{2}$",disabled:editingDisabled,onChange:newValue=>onChangeProps({text:newValue})})]}),jsxRuntimeExports.jsxs(InfoTip,{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,{className:`${styles$o.row} ${styles$o.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,editingDisabled:editingDisabled,onChange:newColor=>{onChangeProps({color:newColor});},style:spaceUnderStyle$3}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$o.row} ${styles$o.sizeLabel}`,children:["size",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:size,disabled:editingDisabled,onChange:newValue=>onChangeProps({size:newValue}),options:{small:"small",medium:"medium",large:"large"}})]})]}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})}
1729
+ const spaceUnderStyle$3={marginBottom:sizing.size_080};function LockedLabelSettings(props){const{type,coord,color,size,text,expanded,editingDisabled=false,onChangeProps,onMove,onRemove,onToggle,containerStyle}=props;return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(View,{className:`${styles$n.row} ${styles$n.accordionHeaderContainer} ${styles$n.header}`,children:[jsxRuntimeExports.jsxs(BodyText,{size:"medium",weight:"bold",tag:"span",children:["Label (",coord[0],", ",coord[1],")"]}),text!==""&&jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",className:styles$n.accordionHeader,style:{color:lockedFigureColors[color]},children:text})]}),containerStyle:containerStyle,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,disabled:editingDisabled,onChange:newCoords=>{onChangeProps({coord:newCoords});},style:spaceUnderStyle$3}),jsxRuntimeExports.jsxs(View,{className:styles$n.row,children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$n.row} ${styles$n.textLabel}`,children:["text",jsxRuntimeExports.jsx(TextField,{value:text,placeholder:"ex. $x^2$ or $\\frac{1}{2}$",disabled:editingDisabled,onChange:newValue=>onChangeProps({text:newValue})})]}),jsxRuntimeExports.jsxs(InfoTip,{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,{className:`${styles$n.row} ${styles$n.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,editingDisabled:editingDisabled,onChange:newColor=>{onChangeProps({color:newColor});},style:spaceUnderStyle$3}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$n.row} ${styles$n.sizeLabel}`,children:["size",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:size,disabled:editingDisabled,onChange:newValue=>onChangeProps({size:newValue}),options:{small:"small",medium:"medium",large:"large"}})]})]}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})}
1729
1730
 
1730
1731
  function generateLockedFigureAppearanceDescription(color,strokeStyle="solid",fill,weight="medium"){const convertedColor=color==="grayH"?"gray":color;const weightString=weight==="medium"?"":` ${weight}`;const strokeDescription=strokeStyle==="none"?"no":`${strokeStyle} ${convertedColor}`;const baseAppearance=`. Appearance${weightString} ${strokeDescription}`;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(", ")}`}
1731
1732
 
1732
- const{convertRadiansToDegrees}=angles;const spaceUnderStyle$2={marginBottom:sizing.size_080};const labelContainerStyle$3={backgroundColor:semanticColor.core.background.base.default};const LockedEllipseSettings=props=>{const{center,radius,angle,color,labels,ariaLabel,fillStyle,strokeStyle,weight,expanded,editingDisabled=false,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,{className:`${styles$r.row} ${styles$r.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",tag:"span",weight:"bold",children:`Ellipse (${center[0]}, ${center[1]}), radius ${radius[0]}, ${radius[1]}`}),jsxRuntimeExports.jsx(EllipseSwatch,{color:props.color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{className:styles$r.row,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:center,style:spaceUnderStyle$2,disabled:editingDisabled,onChange:handleCenterChange}),jsxRuntimeExports.jsx(View,{className:styles$r.spaceUnder,children:jsxRuntimeExports.jsx(InfoTip,{children:"The coordinates for the center of the ellipse."})})]}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:radius,labels:["x radius","y radius"],style:spaceUnderStyle$2,disabled:editingDisabled,onChange:newCoords=>onChangeProps({radius:newCoords})}),jsxRuntimeExports.jsx(AngleInput,{angle:angle,onChange:newAngle=>onChangeProps({angle:newAngle})}),jsxRuntimeExports.jsxs(View,{className:`${styles$r.row} ${styles$r.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$r.row} ${styles$r.truncatedWidth} ${styles$r.fillLabel}`,children:["fill",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:fillStyle,disabled:editingDisabled,onChange:value=>onChangeProps({fillStyle:value}),options:{none:"none",white:"white",translucent:"translucent",solid:"solid"}})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,options:fillableStrokeStyleOptions,editingDisabled:editingDisabled,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:{marginBottom:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsx(View,{className:`${styles$r.horizontalRule} ${styles$r.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$r.horizontalRule} ${styles$r.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$r.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle$3})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[center[0],center[1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},className:styles$r.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1733
+ const{convertRadiansToDegrees}=angles;const spaceUnderStyle$2={marginBottom:sizing.size_080};const labelContainerStyle$3={backgroundColor:semanticColor.core.background.base.default};const LockedEllipseSettings=props=>{const{center,radius,angle,color,labels,ariaLabel,fillStyle,strokeStyle,weight,expanded,editingDisabled=false,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,{className:`${styles$q.row} ${styles$q.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",tag:"span",weight:"bold",children:`Ellipse (${center[0]}, ${center[1]}), radius ${radius[0]}, ${radius[1]}`}),jsxRuntimeExports.jsx(EllipseSwatch,{color:props.color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{className:styles$q.row,children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:center,style:spaceUnderStyle$2,disabled:editingDisabled,onChange:handleCenterChange}),jsxRuntimeExports.jsx(View,{className:styles$q.spaceUnder,children:jsxRuntimeExports.jsx(InfoTip,{children:"The coordinates for the center of the ellipse."})})]}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:radius,labels:["x radius","y radius"],style:spaceUnderStyle$2,disabled:editingDisabled,onChange:newCoords=>onChangeProps({radius:newCoords})}),jsxRuntimeExports.jsx(AngleInput,{angle:angle,onChange:newAngle=>onChangeProps({angle:newAngle})}),jsxRuntimeExports.jsxs(View,{className:`${styles$q.row} ${styles$q.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$q.row} ${styles$q.truncatedWidth} ${styles$q.fillLabel}`,children:["fill",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:fillStyle,disabled:editingDisabled,onChange:value=>onChangeProps({fillStyle:value}),options:{none:"none",white:"white",translucent:"translucent",solid:"solid"}})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,options:fillableStrokeStyleOptions,editingDisabled:editingDisabled,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:{marginBottom:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsx(View,{className:`${styles$q.horizontalRule} ${styles$q.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$q.horizontalRule} ${styles$q.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$q.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle$3})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[center[0],center[1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},className:styles$q.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1733
1734
 
1734
- const LineSwatch=props=>{const{color,lineStyle}=props;return jsxRuntimeExports.jsx(View,{style:styles$n.container,children:jsxRuntimeExports.jsx(View,{"aria-label":`${color}, ${lineStyle}`,style:[styles$n.lineSwatch,{border:`5px ${lineStyle} ${lockedFigureColors[color]}`}]})})};const styles$n=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.base.default,justifyContent:"center",padding:spacing.xSmall_8,borderRadius:spacing.xxxSmall_4},lineSwatch:{width:40}});
1735
+ const LineSwatch=props=>{const{color,lineStyle}=props;return jsxRuntimeExports.jsx(View,{style:styles$m.container,children:jsxRuntimeExports.jsx(View,{"aria-label":`${color}, ${lineStyle}`,style:[styles$m.lineSwatch,{border:`5px ${lineStyle} ${lockedFigureColors[color]}`}]})})};const styles$m=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.base.default,justifyContent:"center",padding:spacing.xSmall_8,borderRadius:spacing.xxxSmall_4},lineSwatch:{width:40}});
1735
1736
 
1736
1737
  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"]};
1737
1738
 
1738
- var styles$m = {"accordionHeader":"perseus_tXEvWJUz","axisMenu":"perseus_3xCRJZPa","copyPasteButton":"perseus_jQjspEma","domainMin":"perseus_sKC9BNwU","domainMax":"perseus_FKW3Nxnm","dropdownLabel":"perseus_yi6yIVkG","exampleContainer":"perseus_4hIadz5F","exampleContent":"perseus_Im9FqKCL","exampleRow":"perseus_XTGXne8n","rowSpace":"perseus_pLyszuFy","row":"perseus_QcmxeGEV","header":"perseus_n6hVg5Q8","colorRow":"perseus_lTxTG2gH","axisRow":"perseus_-uNx1-Ee","domainRow":"perseus_ledp5RIf","addButton":"perseus_hZeYfTVX","horizontalRule":"perseus_MdlHBO-Z","sectionTop":"perseus_f26X1kQX","dividerTight":"perseus_xD6EJyrU","exampleContentIndent":"perseus_BlYv-O-3"};
1739
+ var styles$l = {"accordionHeader":"perseus_tXEvWJUz","axisMenu":"perseus_3xCRJZPa","copyPasteButton":"perseus_jQjspEma","domainMin":"perseus_sKC9BNwU","domainMax":"perseus_FKW3Nxnm","dropdownLabel":"perseus_yi6yIVkG","exampleContainer":"perseus_4hIadz5F","exampleContent":"perseus_Im9FqKCL","exampleRow":"perseus_XTGXne8n","rowSpace":"perseus_pLyszuFy","row":"perseus_QcmxeGEV","header":"perseus_n6hVg5Q8","colorRow":"perseus_lTxTG2gH","axisRow":"perseus_-uNx1-Ee","domainRow":"perseus_ledp5RIf","addButton":"perseus_hZeYfTVX","horizontalRule":"perseus_MdlHBO-Z","sectionTop":"perseus_f26X1kQX","dividerTight":"perseus_xD6EJyrU","exampleContentIndent":"perseus_BlYv-O-3"};
1739
1740
 
1740
- const LockedFunctionSettings=props=>{const{color:lineColor,strokeStyle,equation,directionalAxis,domain,weight,ariaLabel,editingDisabled=false,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(null);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 exampleContent=exampleCategory!=null?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,{className:`${styles$m.row} ${styles$m.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",className:styles$m.accordionHeader,children:lineLabel}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{className:`${styles$m.row} ${styles$m.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,options:lineStrokeStyleOptions,editingDisabled:editingDisabled,onChange:newValue=>{handlePropChange("strokeStyle",newValue);}})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsxs(View,{className:`${styles$m.row} ${styles$m.rowSpace} ${styles$m.axisRow}`,children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:directionalAxis,disabled:editingDisabled,options:{x:"y =",y:"x ="},onChange:newValue=>{handlePropChange("directionalAxis",newValue);},"aria-label":"equation prefix",className:`${styles$m.dropdownLabel} ${styles$m.axisMenu}`}),jsxRuntimeExports.jsx(TextField,{type:"text","aria-label":"equation",value:equation,disabled:editingDisabled,onChange:newValue=>{handlePropChange("equation",newValue);},style:{flexGrow:1}})]}),jsxRuntimeExports.jsxs(View,{className:`${styles$m.row} ${styles$m.rowSpace} ${styles$m.domainRow}`,children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$m.dropdownLabel} ${styles$m.domainMin}`,children:["domain min",jsxRuntimeExports.jsx(TextField,{type:"number",style:{width:"calc(100% - 88.7px)"},value:domainEntries[0],disabled:editingDisabled,onChange:newValue=>{handleDomainChange(0,newValue);}})]}),jsxRuntimeExports.jsxs(BodyText,{tag:"label","aria-label":"domain max",className:`${styles$m.dropdownLabel} ${styles$m.domainMax}`,children:["max",jsxRuntimeExports.jsx(TextField,{type:"number",style:{width:"calc(100% - 36.2px)"},value:domainEntries[1],disabled:editingDisabled,onChange:newValue=>{handleDomainChange(1,newValue);}})]})]}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:"Example Functions"}),expanded:false,containerStyle:{background:semanticColor.core.background.base.subtle},panelStyle:{alignItems:"start",paddingBottom:sizing.size_120,flexDirection:"row",flexWrap:"wrap"},children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$m.dropdownLabel,children:["Choose a category",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:exampleCategory,disabled:editingDisabled,options:{linear:"linear",polynomial:"polynomial",trigonometric:"trigonometric"},onChange:setExampleCategory,placeholder:"examples"})]}),exampleCategory!=null&&jsxRuntimeExports.jsx("ul",{className:styles$m.exampleContainer,children:exampleContent.map((example,index)=>jsxRuntimeExports.jsx(ExampleItem,{category:exampleCategory,example:example,index:index,editingDisabled:editingDisabled,pasteEquationFn:handlePropChange},index))})]}),jsxRuntimeExports.jsx(View,{className:`${styles$m.horizontalRule} ${styles$m.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$m.horizontalRule} ${styles$m.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$m.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>jsxRuntimeExports.jsx(LockedLabelSettings,{...label,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:{backgroundColor:semanticColor.core.background.base.default}},labelIndex)),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[0,-labels.length],color:lineColor};onChangeProps({labels:[...labels,newLabel]});},className:styles$m.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};const ExampleItem=props=>{const{category,example,index,editingDisabled,pasteEquationFn}=props;const exampleId=useId();return jsxRuntimeExports.jsxs("li",{className:styles$m.exampleRow,children:[jsxRuntimeExports.jsx(IconButton,{icon:autoPasteIcon,kind:"tertiary","aria-label":"paste example","aria-describedby":exampleId,disabled:editingDisabled,onClick:()=>pasteEquationFn("equation",example),size:"medium",className:styles$m.copyPasteButton}),jsxRuntimeExports.jsx(IconButton,{icon:copyIcon,kind:"tertiary","aria-label":"copy example","aria-describedby":exampleId,disabled:editingDisabled,onClick:()=>navigator.clipboard.writeText(example),size:"medium",className:styles$m.copyPasteButton}),jsxRuntimeExports.jsx(View,{className:`${styles$m.exampleContent} ${styles$m.exampleContentIndent}`,id:exampleId,children:example})]},`${category}-${index}`)};
1741
+ const LockedFunctionSettings=props=>{const{color:lineColor,strokeStyle,equation,directionalAxis,domain,weight,ariaLabel,editingDisabled=false,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(null);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 exampleContent=exampleCategory!=null?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,{className:`${styles$l.row} ${styles$l.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",className:styles$l.accordionHeader,children:lineLabel}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{className:`${styles$l.row} ${styles$l.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,options:lineStrokeStyleOptions,editingDisabled:editingDisabled,onChange:newValue=>{handlePropChange("strokeStyle",newValue);}})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsxs(View,{className:`${styles$l.row} ${styles$l.rowSpace} ${styles$l.axisRow}`,children:[jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:directionalAxis,disabled:editingDisabled,options:{x:"y =",y:"x ="},onChange:newValue=>{handlePropChange("directionalAxis",newValue);},"aria-label":"equation prefix",className:`${styles$l.dropdownLabel} ${styles$l.axisMenu}`}),jsxRuntimeExports.jsx(TextField,{type:"text","aria-label":"equation",value:equation,disabled:editingDisabled,onChange:newValue=>{handlePropChange("equation",newValue);},style:{flexGrow:1}})]}),jsxRuntimeExports.jsxs(View,{className:`${styles$l.row} ${styles$l.rowSpace} ${styles$l.domainRow}`,children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$l.dropdownLabel} ${styles$l.domainMin}`,children:["domain min",jsxRuntimeExports.jsx(TextField,{type:"number",style:{width:"calc(100% - 88.7px)"},value:domainEntries[0],disabled:editingDisabled,onChange:newValue=>{handleDomainChange(0,newValue);}})]}),jsxRuntimeExports.jsxs(BodyText,{tag:"label","aria-label":"domain max",className:`${styles$l.dropdownLabel} ${styles$l.domainMax}`,children:["max",jsxRuntimeExports.jsx(TextField,{type:"number",style:{width:"calc(100% - 36.2px)"},value:domainEntries[1],disabled:editingDisabled,onChange:newValue=>{handleDomainChange(1,newValue);}})]})]}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:"Example Functions"}),expanded:false,containerStyle:{background:semanticColor.core.background.base.subtle},panelStyle:{alignItems:"start",paddingBottom:sizing.size_120,flexDirection:"row",flexWrap:"wrap"},children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$l.dropdownLabel,children:["Choose a category",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:exampleCategory,disabled:editingDisabled,options:{linear:"linear",polynomial:"polynomial",trigonometric:"trigonometric"},onChange:setExampleCategory,placeholder:"examples"})]}),exampleCategory!=null&&jsxRuntimeExports.jsx("ul",{className:styles$l.exampleContainer,children:exampleContent.map((example,index)=>jsxRuntimeExports.jsx(ExampleItem,{category:exampleCategory,example:example,index:index,editingDisabled:editingDisabled,pasteEquationFn:handlePropChange},index))})]}),jsxRuntimeExports.jsx(View,{className:`${styles$l.horizontalRule} ${styles$l.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$l.horizontalRule} ${styles$l.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$l.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>jsxRuntimeExports.jsx(LockedLabelSettings,{...label,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:{backgroundColor:semanticColor.core.background.base.default}},labelIndex)),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[0,-labels.length],color:lineColor};onChangeProps({labels:[...labels,newLabel]});},className:styles$l.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};const ExampleItem=props=>{const{category,example,index,editingDisabled,pasteEquationFn}=props;const exampleId=useId();return jsxRuntimeExports.jsxs("li",{className:styles$l.exampleRow,children:[jsxRuntimeExports.jsx(IconButton,{icon:autoPasteIcon,kind:"tertiary","aria-label":"paste example","aria-describedby":exampleId,disabled:editingDisabled,onClick:()=>pasteEquationFn("equation",example),size:"medium",className:styles$l.copyPasteButton}),jsxRuntimeExports.jsx(IconButton,{icon:copyIcon,kind:"tertiary","aria-label":"copy example","aria-describedby":exampleId,disabled:editingDisabled,onClick:()=>navigator.clipboard.writeText(example),size:"medium",className:styles$l.copyPasteButton}),jsxRuntimeExports.jsx(View,{className:`${styles$l.exampleContent} ${styles$l.exampleContentIndent}`,id:exampleId,children:example})]},`${category}-${index}`)};
1741
1742
 
1742
- var styles$l = {"row":"perseus_nBzKD32m","header":"perseus_WNElRLBL","spaceUnder":"perseus_sEXwoqeH","kindLabel":"perseus_MohIPkUC","colorRow":"perseus_WDC67hHF","errorText":"perseus_57zeueK9","addButton":"perseus_se9nOPo3","horizontalRule":"perseus_XnNJefSQ","sectionTop":"perseus_mCvSm-pU","dividerTight":"perseus_34Yfh9Ri"};
1743
+ var styles$k = {"row":"perseus_nBzKD32m","header":"perseus_WNElRLBL","spaceUnder":"perseus_sEXwoqeH","kindLabel":"perseus_MohIPkUC","colorRow":"perseus_WDC67hHF","errorText":"perseus_57zeueK9","addButton":"perseus_se9nOPo3","horizontalRule":"perseus_XnNJefSQ","sectionTop":"perseus_mCvSm-pU","dividerTight":"perseus_34Yfh9Ri"};
1743
1744
 
1744
- var styles$k = {"row":"perseus_PsQTUHiB","addButton":"perseus_DzebTj-c","horizontalRule":"perseus_pxo33u6Q","sectionTop":"perseus_pOW3mBVq","dividerTight":"perseus_iXTo2lsa"};
1745
+ var styles$j = {"row":"perseus_PsQTUHiB","addButton":"perseus_DzebTj-c","horizontalRule":"perseus_pxo33u6Q","sectionTop":"perseus_pOW3mBVq","dividerTight":"perseus_iXTo2lsa"};
1745
1746
 
1746
- const spaceUnderStyle$1={marginBottom:sizing.size_080};const LockedPointSettings=props=>{const{headerLabel,editingDisabled=false,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,"solid",filled?undefined:"none");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?{marginTop:sizing.size_080,marginBottom:0,marginLeft:-sizing.size_040,marginRight:-sizing.size_040,backgroundColor:semanticColor.core.background.base.default}:undefined,panelStyle:isDefiningPoint?{paddingBottom:sizing.size_060}:undefined,header:jsxRuntimeExports.jsxs(View,{className:styles$k.row,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`${headerLabel||"Point"} (${coord[0]}, ${coord[1]})`}),jsxRuntimeExports.jsx(ColorSwatch,{color:pointColor,filled:filled})]}),children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,style:spaceUnderStyle$1,disabled:editingDisabled,onChange:handleCoordChange,error:!!error}),onTogglePoint&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"show point on graph",checked:!!showPoint,style:showPoint&&spaceUnderStyle$1,disabled:editingDisabled,onChange:onTogglePoint}),(!isDefiningPoint||showPoint)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:pointColor,onChange:handleColorChange,style:spaceUnderStyle$1,editingDisabled:editingDisabled}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"open point",checked:!filled,disabled:editingDisabled,onChange:newValue=>{onChangeProps({filled:!newValue});}})]}),!isDefiningPoint&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(View,{className:`${styles$k.horizontalRule} ${styles$k.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}})]}),jsxRuntimeExports.jsx(View,{className:`${styles$k.horizontalRule} ${styles$k.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$k.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,containerStyle:!isDefiningPoint&&{backgroundColor:semanticColor.core.background.base.default},expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);}})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[coord[0]+.5,coord[1]-labels.length],color:pointColor};onChangeProps({labels:[...labels,newLabel]});},className:styles$k.addButton,children:"Add visible label"}),onRemove&&jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1747
+ const spaceUnderStyle$1={marginBottom:sizing.size_080};const LockedPointSettings=props=>{const{headerLabel,editingDisabled=false,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,"solid",filled?undefined:"none");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?{marginTop:sizing.size_080,marginBottom:0,marginLeft:-sizing.size_040,marginRight:-sizing.size_040,backgroundColor:semanticColor.core.background.base.default}:undefined,panelStyle:isDefiningPoint?{paddingBottom:sizing.size_060}:undefined,header:jsxRuntimeExports.jsxs(View,{className:styles$j.row,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`${headerLabel||"Point"} (${coord[0]}, ${coord[1]})`}),jsxRuntimeExports.jsx(ColorSwatch,{color:pointColor,filled:filled})]}),children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,style:spaceUnderStyle$1,disabled:editingDisabled,onChange:handleCoordChange,error:!!error}),onTogglePoint&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"show point on graph",checked:!!showPoint,style:showPoint&&spaceUnderStyle$1,disabled:editingDisabled,onChange:onTogglePoint}),(!isDefiningPoint||showPoint)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:pointColor,onChange:handleColorChange,style:spaceUnderStyle$1,editingDisabled:editingDisabled}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"open point",checked:!filled,disabled:editingDisabled,onChange:newValue=>{onChangeProps({filled:!newValue});}})]}),!isDefiningPoint&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(View,{className:`${styles$j.horizontalRule} ${styles$j.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}})]}),jsxRuntimeExports.jsx(View,{className:`${styles$j.horizontalRule} ${styles$j.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$j.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,containerStyle:!isDefiningPoint&&{backgroundColor:semanticColor.core.background.base.default},expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);}})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[coord[0]+.5,coord[1]-labels.length],color:pointColor};onChangeProps({labels:[...labels,newLabel]});},className:styles$j.addButton,children:"Add visible label"}),onRemove&&jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1747
1748
 
1748
1749
  const lengthZeroStr="The line cannot have length 0.";const labelContainerStyle$2={backgroundColor:semanticColor.core.background.base.default};const LockedLineSettings=props=>{const{kind,points,color:lineColor,lineStyle="solid",showPoint1,showPoint2,weight,labels,ariaLabel,editingDisabled=false,onChangeProps,onMove,onRemove}=props;const[point1,point2]=points;const capitalizeKind=kind.charAt(0).toUpperCase()+kind.slice(1);const lineLabel=`${capitalizeKind} (${point1.coord[0]},
1749
- ${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,{className:`${styles$l.row} ${styles$l.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:lineLabel}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:lineStyle})]}),children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$l.row} ${styles$l.spaceUnder} ${styles$l.kindLabel}`,children:["kind",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:kind,disabled:editingDisabled,onChange:value=>onChangeProps({kind:value}),options:{line:"line",ray:"ray",segment:"segment"}})]}),jsxRuntimeExports.jsxs(View,{className:`${styles$l.row} ${styles$l.spaceUnder} ${styles$l.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:lineStyle,options:lineStrokeStyleOptions,editingDisabled:editingDisabled,onChange:value=>onChangeProps({lineStyle:value})})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(BodyText,{className:styles$l.errorText,children:lengthZeroStr}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 1",expanded:true,showPoint:showPoint1,error:isInvalid?lengthZeroStr:null,...point1,editingDisabled:editingDisabled,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,editingDisabled:editingDisabled,onTogglePoint:newValue=>onChangeProps({showPoint2:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,1)}),jsxRuntimeExports.jsx(View,{className:`${styles$l.horizontalRule} ${styles$l.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$l.horizontalRule} ${styles$l.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$l.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle$2})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,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]});},className:styles$l.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1750
+ ${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,{className:`${styles$k.row} ${styles$k.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:lineLabel}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:lineStyle})]}),children:[jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$k.row} ${styles$k.spaceUnder} ${styles$k.kindLabel}`,children:["kind",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:kind,disabled:editingDisabled,onChange:value=>onChangeProps({kind:value}),options:{line:"line",ray:"ray",segment:"segment"}})]}),jsxRuntimeExports.jsxs(View,{className:`${styles$k.row} ${styles$k.spaceUnder} ${styles$k.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:lineStyle,options:lineStrokeStyleOptions,editingDisabled:editingDisabled,onChange:value=>onChangeProps({lineStyle:value})})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(BodyText,{className:styles$k.errorText,children:lengthZeroStr}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 1",expanded:true,showPoint:showPoint1,error:isInvalid?lengthZeroStr:null,...point1,editingDisabled:editingDisabled,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,editingDisabled:editingDisabled,onTogglePoint:newValue=>onChangeProps({showPoint2:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,1)}),jsxRuntimeExports.jsx(View,{className:`${styles$k.horizontalRule} ${styles$k.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$k.horizontalRule} ${styles$k.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$k.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle$2})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,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]});},className:styles$k.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1750
1751
 
1751
- var styles$j = {"row":"perseus_7gvpLIxX","header":"perseus_a9dhxydf","spaceUnder":"perseus_FMC5CN4y","colorRow":"perseus_bj3iyVpL","fillLabel":"perseus_gbGj72Hu","icon":"perseus_DYnWU1Yr","polygonActionsContainer":"perseus_YhcLg4qs","movementButtonsContainer":"perseus_DtEDhGzL","truncatedWidth":"perseus_14L-Mr6p","addButton":"perseus_dc8k1hRY","horizontalRule":"perseus_iR-te9L8","sectionTop":"perseus_q3l-Nth6","dividerTight":"perseus_WNA-ZWQ8"};
1752
+ var styles$i = {"row":"perseus_7gvpLIxX","header":"perseus_a9dhxydf","spaceUnder":"perseus_FMC5CN4y","colorRow":"perseus_bj3iyVpL","fillLabel":"perseus_gbGj72Hu","icon":"perseus_DYnWU1Yr","polygonActionsContainer":"perseus_YhcLg4qs","movementButtonsContainer":"perseus_DtEDhGzL","truncatedWidth":"perseus_14L-Mr6p","addButton":"perseus_dc8k1hRY","horizontalRule":"perseus_iR-te9L8","sectionTop":"perseus_q3l-Nth6","dividerTight":"perseus_WNA-ZWQ8"};
1752
1753
 
1753
- const PolygonSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$i.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$i.innerSquare,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$i=StyleSheet.create({container:{outline:`2px solid ${semanticColor.focus.inner}`,width:spacing.large_24,height:spacing.large_24,backgroundColor:semanticColor.core.background.base.default,alignItems:"center",justifyContent:"center"},innerSquare:{width:20,height:20}});
1754
+ const PolygonSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$h.container,{border:`4px ${strokeStyle} ${lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(View,{style:[styles$h.innerSquare,{backgroundColor:lockedFigureColors[color],opacity:fillStyle==="white"?0:lockedFigureFillStyles[fillStyle]}]})})};const styles$h=StyleSheet.create({container:{outline:`2px solid ${semanticColor.focus.inner}`,width:spacing.large_24,height:spacing.large_24,backgroundColor:semanticColor.core.background.base.default,alignItems:"center",justifyContent:"center"},innerSquare:{width:20,height:20}});
1754
1755
 
1755
- const spaceUnderStyle={marginBottom:sizing.size_080};const pointAccordionContainerStyle={backgroundColor:semanticColor.core.background.base.default};const pointAccordionPanelStyle={alignItems:"start"};const labelContainerStyle$1={backgroundColor:semanticColor.core.background.base.default};const LockedPolygonSettings=props=>{const{points,color,showVertices,fillStyle,strokeStyle,weight,labels,ariaLabel,expanded,editingDisabled=false,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,{className:`${styles$j.row} ${styles$j.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`Polygon, ${points.length} sides`}),jsxRuntimeExports.jsx(PolygonSwatch,{color:color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{className:`${styles$j.row} ${styles$j.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$j.row} ${styles$j.truncatedWidth} ${styles$j.fillLabel}`,children:["fill",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:fillStyle,disabled:editingDisabled,onChange:value=>onChangeProps({fillStyle:value}),options:{none:"none",white:"white",translucent:"translucent",solid:"solid"}})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,options:fillableStrokeStyleOptions,editingDisabled:editingDisabled,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:spaceUnderStyle}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value}),containerStyle:spaceUnderStyle}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"show vertices",checked:showVertices,disabled:editingDisabled,onChange:newValue=>onChangeProps({showVertices:newValue}),style:spaceUnderStyle}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:"Points"}),expanded:true,containerStyle:pointAccordionContainerStyle,panelStyle:pointAccordionPanelStyle,children:[points.map((point,index)=>{const pointLabel=String.fromCharCode(65+index);return jsxRuntimeExports.jsxs(View,{className:`${styles$j.row} ${styles$j.spaceUnder}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",children:`${pointLabel}:`}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:point,labels:["x","y"],style:{marginInlineStart:sizing.size_160},disabled:editingDisabled,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",disabled:editingDisabled,onClick:()=>{const newPoints=[...points];newPoints.splice(index,1);props.onChangeProps({points:newPoints});},className:styles$j.icon})]},`locked-polygon-point-index-${index}`)}),jsxRuntimeExports.jsxs(View,{className:`${styles$j.row} ${styles$j.polygonActionsContainer}`,children:[jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{props.onChangeProps({points:[...points,[0,0]]});},children:"Add point"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(View,{className:styles$j.movementButtonsContainer,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon up",size:"small",icon:arrowFatUp,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("up")}),jsxRuntimeExports.jsxs(View,{className:styles$j.row,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon left",size:"small",icon:arrowFatLeft,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("left")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon down",size:"small",icon:arrowFatDown,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("down")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon right",size:"small",icon:arrowFatRight,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("right")})]})]})]})]}),jsxRuntimeExports.jsx(View,{className:`${styles$j.horizontalRule} ${styles$j.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$j.horizontalRule} ${styles$j.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$j.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle$1})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[points[0][0],points[0][1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},className:styles$j.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1756
+ const spaceUnderStyle={marginBottom:sizing.size_080};const pointAccordionContainerStyle={backgroundColor:semanticColor.core.background.base.default};const pointAccordionPanelStyle={alignItems:"start"};const labelContainerStyle$1={backgroundColor:semanticColor.core.background.base.default};const LockedPolygonSettings=props=>{const{points,color,showVertices,fillStyle,strokeStyle,weight,labels,ariaLabel,expanded,editingDisabled=false,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,{className:`${styles$i.row} ${styles$i.header}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`Polygon, ${points.length} sides`}),jsxRuntimeExports.jsx(PolygonSwatch,{color:color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(View,{className:`${styles$i.row} ${styles$i.colorRow}`,children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,editingDisabled:editingDisabled,onChange:handleColorChange}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:`${styles$i.row} ${styles$i.truncatedWidth} ${styles$i.fillLabel}`,children:["fill",jsxRuntimeExports.jsx(TypedSingleSelect,{selectedValue:fillStyle,disabled:editingDisabled,onChange:value=>onChangeProps({fillStyle:value}),options:{none:"none",white:"white",translucent:"translucent",solid:"solid"}})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,options:fillableStrokeStyleOptions,editingDisabled:editingDisabled,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:spaceUnderStyle}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value}),containerStyle:spaceUnderStyle}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"show vertices",checked:showVertices,disabled:editingDisabled,onChange:newValue=>onChangeProps({showVertices:newValue}),style:spaceUnderStyle}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:"Points"}),expanded:true,containerStyle:pointAccordionContainerStyle,panelStyle:pointAccordionPanelStyle,children:[points.map((point,index)=>{const pointLabel=String.fromCharCode(65+index);return jsxRuntimeExports.jsxs(View,{className:`${styles$i.row} ${styles$i.spaceUnder}`,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",children:`${pointLabel}:`}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:point,labels:["x","y"],style:{marginInlineStart:sizing.size_160},disabled:editingDisabled,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",disabled:editingDisabled,onClick:()=>{const newPoints=[...points];newPoints.splice(index,1);props.onChangeProps({points:newPoints});},className:styles$i.icon})]},`locked-polygon-point-index-${index}`)}),jsxRuntimeExports.jsxs(View,{className:`${styles$i.row} ${styles$i.polygonActionsContainer}`,children:[jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{props.onChangeProps({points:[...points,[0,0]]});},children:"Add point"}),jsxRuntimeExports.jsx(Spring,{}),jsxRuntimeExports.jsxs(View,{className:styles$i.movementButtonsContainer,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon up",size:"small",icon:arrowFatUp,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("up")}),jsxRuntimeExports.jsxs(View,{className:styles$i.row,children:[jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon left",size:"small",icon:arrowFatLeft,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("left")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon down",size:"small",icon:arrowFatDown,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("down")}),jsxRuntimeExports.jsx(IconButton,{"aria-label":"Move polygon right",size:"small",icon:arrowFatRight,kind:"tertiary",disabled:editingDisabled,onClick:()=>handlePolygonMove("right")})]})]})]})]}),jsxRuntimeExports.jsx(View,{className:`${styles$i.horizontalRule} ${styles$i.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$i.horizontalRule} ${styles$i.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$i.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle$1})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,onClick:()=>{const newLabel={...getDefaultFigureForType("label"),coord:[points[0][0],points[0][1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},className:styles$i.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1756
1757
 
1757
- var styles$h = {"row":"perseus_Ug-lFL8r","errorText":"perseus_6gvwJ939","addButton":"perseus_vcxh5KIo","horizontalRule":"perseus_HRitDKmQ","sectionTop":"perseus_QY6CaDZH","dividerTight":"perseus_QDq7G5V4"};
1758
+ var styles$g = {"row":"perseus_Ug-lFL8r","errorText":"perseus_6gvwJ939","addButton":"perseus_vcxh5KIo","horizontalRule":"perseus_HRitDKmQ","sectionTop":"perseus_QY6CaDZH","dividerTight":"perseus_QDq7G5V4"};
1758
1759
 
1759
- const lengthErrorMessage="The vector cannot have length 0.";const coordsAccordionContainerStyle={marginTop:sizing.size_080,marginBottom:0,marginLeft:-sizing.size_040,marginRight:-sizing.size_040,backgroundColor:semanticColor.core.background.base.default};const coordsAccordionPanelStyle={paddingBottom:sizing.size_160};const labelContainerStyle={backgroundColor:semanticColor.core.background.base.default};const LockedVectorSettings=props=>{const{points,color:lineColor,weight,labels,ariaLabel,editingDisabled=false,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,{className:styles$h.row,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:lineLabel}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:"solid"})]}),children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,editingDisabled:editingDisabled,onChange:handleColorChange,style:{marginBlockEnd:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(BodyText,{className:styles$h.errorText,children:lengthErrorMessage}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:coordsAccordionContainerStyle,panelStyle:coordsAccordionPanelStyle,header:jsxRuntimeExports.jsx(View,{className:styles$h.row,children:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`Tail (${tail[0]}, ${tail[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tail,error:isInvalid,disabled:editingDisabled,onChange:newProps=>{handleChangePoint(newProps,0);}})}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:coordsAccordionContainerStyle,panelStyle:coordsAccordionPanelStyle,header:jsxRuntimeExports.jsx(View,{className:styles$h.row,children:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`Tip (${tip[0]}, ${tip[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tip,error:isInvalid,disabled:editingDisabled,onChange:newProps=>{handleChangePoint(newProps,1);}})}),jsxRuntimeExports.jsx(View,{className:`${styles$h.horizontalRule} ${styles$h.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$h.horizontalRule} ${styles$h.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$h.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,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]});},className:styles$h.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1760
+ const lengthErrorMessage="The vector cannot have length 0.";const coordsAccordionContainerStyle={marginTop:sizing.size_080,marginBottom:0,marginLeft:-sizing.size_040,marginRight:-sizing.size_040,backgroundColor:semanticColor.core.background.base.default};const coordsAccordionPanelStyle={paddingBottom:sizing.size_160};const labelContainerStyle={backgroundColor:semanticColor.core.background.base.default};const LockedVectorSettings=props=>{const{points,color:lineColor,weight,labels,ariaLabel,editingDisabled=false,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,{className:styles$g.row,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:lineLabel}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:"solid"})]}),children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,editingDisabled:editingDisabled,onChange:handleColorChange,style:{marginBlockEnd:sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,editingDisabled:editingDisabled,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(BodyText,{className:styles$g.errorText,children:lengthErrorMessage}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:coordsAccordionContainerStyle,panelStyle:coordsAccordionPanelStyle,header:jsxRuntimeExports.jsx(View,{className:styles$g.row,children:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`Tail (${tail[0]}, ${tail[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tail,error:isInvalid,disabled:editingDisabled,onChange:newProps=>{handleChangePoint(newProps,0);}})}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:coordsAccordionContainerStyle,panelStyle:coordsAccordionPanelStyle,header:jsxRuntimeExports.jsx(View,{className:styles$g.row,children:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`Tip (${tip[0]}, ${tip[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tip,error:isInvalid,disabled:editingDisabled,onChange:newProps=>{handleChangePoint(newProps,1);}})}),jsxRuntimeExports.jsx(View,{className:`${styles$g.horizontalRule} ${styles$g.sectionTop}`}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,editingDisabled:editingDisabled,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(View,{className:`${styles$g.horizontalRule} ${styles$g.dividerTight}`}),jsxRuntimeExports.jsx(BodyText,{className:styles$g.sectionTop,children:"Visible labels"}),labels.map((label,labelIndex)=>createElement(LockedLabelSettings,{...label,key:labelIndex,editingDisabled:editingDisabled,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:labelContainerStyle})),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,disabled:editingDisabled,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]});},className:styles$g.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,editingDisabled:editingDisabled,onMove:onMove,onRemove:onRemove})]})};
1760
1761
 
1761
1762
  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)}};
1762
1763
 
1763
- var styles$g = {"buttonContainer":"perseus_GL9hZba7","button":"perseus_JRXpziEg"};
1764
+ var styles$f = {"buttonContainer":"perseus_GL9hZba7","button":"perseus_JRXpziEg"};
1764
1765
 
1765
- const LockedFiguresSection=props=>{const editingDisabled=props.apiOptions?.editingDisabled??false;const collapsedStateArray=Array((props.figures??[]).length).fill(editingDisabled);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,editingDisabled:editingDisabled,onChangeProps:newProps=>changeProps(index,newProps),onMove:movement=>moveLockedFigure(index,movement),onRemove:()=>removeLockedFigure(index)},`${uniqueId}-locked-${figure}-${index}`)}),jsxRuntimeExports.jsxs(View,{className:styles$g.buttonContainer,children:[jsxRuntimeExports.jsx(LockedFigureSelect,{id:`${uniqueId}-select`,editingDisabled:editingDisabled,onChange:addLockedFigure}),showExpandButton&&jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:editingDisabled,onClick:()=>toggleExpanded(allCollapsed),className:styles$g.button,children:buttonLabel})]})]})]})};
1766
+ const LockedFiguresSection=props=>{const editingDisabled=props.apiOptions?.editingDisabled??false;const collapsedStateArray=Array((props.figures??[]).length).fill(editingDisabled);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,editingDisabled:editingDisabled,onChangeProps:newProps=>changeProps(index,newProps),onMove:movement=>moveLockedFigure(index,movement),onRemove:()=>removeLockedFigure(index)},`${uniqueId}-locked-${figure}-${index}`)}),jsxRuntimeExports.jsxs(View,{className:styles$f.buttonContainer,children:[jsxRuntimeExports.jsx(LockedFigureSelect,{id:`${uniqueId}-select`,editingDisabled:editingDisabled,onChange:addLockedFigure}),showExpandButton&&jsxRuntimeExports.jsx(Button,{kind:"secondary",disabled:editingDisabled,onClick:()=>toggleExpanded(allCollapsed),className:styles$f.button,children:buttonLabel})]})]})]})};
1766
1767
 
1767
- var styles$f = {"tile":"perseus_9oJAXCGH","tileRow":"perseus_4KcHH9Bl","labelField":"perseus_Ry1WVaFB","labelPrefix":"perseus_aVULDXX8","text-field-wrapper":"perseus_37eFZ7ym","pointLabelField":"perseus_cDLqevTf","equationSection":"perseus_aqjusrqZ","equationBody":"perseus_oT9y-KpN","resetButton":"perseus_sK1-PDYK"};
1768
+ var styles$e = {"tile":"perseus_9oJAXCGH","tileRow":"perseus_4KcHH9Bl","labelField":"perseus_Ry1WVaFB","labelPrefix":"perseus_aVULDXX8","text-field-wrapper":"perseus_37eFZ7ym","pointLabelField":"perseus_cDLqevTf","equationSection":"perseus_aqjusrqZ","equationBody":"perseus_oT9y-KpN","resetButton":"perseus_sK1-PDYK"};
1768
1769
 
1769
- const CoordInput=props=>{const{label,coord,onChange,pointLabel,onPointLabelChange}=props;if(onPointLabelChange){const placeholder=label.match(/\d+$/)?.[0]??label;return jsxRuntimeExports.jsxs(View,{className:styles$f.tile,children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:`${label}:`}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,labels:["x","y"],onChange:onChange,labelClassName:styles$f.labelPrefix}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$f.labelField,children:[jsxRuntimeExports.jsx("span",{className:styles$f.labelPrefix,children:"Label"}),jsxRuntimeExports.jsx(View,{className:styles$f.pointLabelField,children:jsxRuntimeExports.jsx(TextField,{"aria-label":`${label} name`,value:pointLabel??"",placeholder:placeholder,onChange:onPointLabelChange})})]})]})}return jsxRuntimeExports.jsxs(View,{className:styles$f.tileRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:`${label}:`}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,labels:["x","y"],onChange:onChange})]})};
1770
+ const CoordInput=props=>{const{label,coord,onChange,pointLabel,onPointLabelChange}=props;if(onPointLabelChange){const placeholder=label.match(/\d+$/)?.[0]??label;return jsxRuntimeExports.jsxs(View,{className:styles$e.tile,children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:`${label}:`}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,labels:["x","y"],onChange:onChange,labelClassName:styles$e.labelPrefix}),jsxRuntimeExports.jsxs(BodyText,{tag:"label",className:styles$e.labelField,children:[jsxRuntimeExports.jsx("span",{className:styles$e.labelPrefix,children:"Label"}),jsxRuntimeExports.jsx(View,{className:styles$e.pointLabelField,children:jsxRuntimeExports.jsx(TextField,{"aria-label":`${label} name`,value:pointLabel??"",placeholder:placeholder,onChange:onPointLabelChange})})]})]})}return jsxRuntimeExports.jsxs(View,{className:styles$e.tileRow,children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:`${label}:`}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,labels:["x","y"],onChange:onChange})]})};
1770
1771
 
1771
1772
  const StartCoordsAbsoluteValue=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const[vertex,arm]=startCoords;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CoordInput,{label:"Vertex",coord:vertex,onChange:value=>onChange([value,arm]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Arm",coord:arm,onChange:value=>onChange([vertex,value]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)})]})};
1772
1773
 
1773
1774
  const{getClockwiseAngle}=angles;function getStartCoords(graph){if("startCoords"in graph){return graph.startCoords}return undefined}function getDefaultGraphStartCoords(graph,range,step){switch(graph.type){case "absolute-value":return getAbsoluteValueCoords({...graph,startCoords:undefined},range,step);case "linear":case "ray":return getLineCoords({...graph,startCoords:undefined},range,step);case "vector":return getVectorCoords({...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 "exponential":{const{coords,asymptote}=getExponentialCoords({...graph,startCoords:undefined},range,step);return {coords,asymptote}}case "tangent":return getTangentCoords({...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});case "logarithm":{const{coords,asymptote}=getLogarithmCoords({...graph,startCoords:undefined},range,step);return {coords,asymptote}}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 getTangentEquation=startCoords=>{const p1=startCoords[0];const p2=startCoords[1];const amplitude=p2[1]-p1[1];const angularFrequency=Math.PI/(4*(p2[0]-p1[0]));const phase=p1[0]*angularFrequency;const verticalOffset=p1[1];return "y = "+amplitude.toFixed(3)+"tan("+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 getLogarithmEquation=(coords,asymptote)=>{const p1=coords[0];const p2=coords[1];if(p1[1]===p2[1]){return "undefined (points share the same y)"}if(p1[0]===asymptote||p2[0]===asymptote){return "undefined (point on asymptote)"}const ratio=(p1[0]-asymptote)/(p2[0]-asymptote);if(ratio<=0){return "undefined (points on opposite sides of asymptote)"}const bExp=Math.log(ratio)/(p1[1]-p2[1]);const aExp=(p1[0]-asymptote)/Math.exp(bExp*p1[1]);if(!isFinite(bExp)||!isFinite(aExp)||aExp===0||bExp===0){return "undefined (invalid coefficients)"}const a=1/bExp;const b=1/aExp;const c=-asymptote/aExp;return "y = "+a.toFixed(3)+"ln("+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 "exponential":case "linear":case "linear-system":case "tangent":case "quadratic":case "ray":case "segment":case "sinusoid":case "absolute-value":case "logarithm":case "vector":return true;default:throw new UnreachableCaseError(graph)}};
1774
1775
 
1775
- const StartCoordsAngle=props=>{const{startCoords,allowReflexAngles,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??"",index===2?newLabel:pointLabels[2]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$e.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$e.equationBody,children:getAngleEquation(startCoords,allowReflexAngles)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1],startCoords[2]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Vertex",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value,startCoords[2]]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[2],onChange:value=>onChange([startCoords[0],startCoords[1],value]),pointLabel:pointLabels[2],onPointLabelChange:newLabel=>updatePointLabel(2,newLabel)})]})};const styles$e=StyleSheet.create({equationSection:{marginBlockStart:spacing.small_12},equationBody:{backgroundColor:semanticColor.core.background.neutral.subtle,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,marginBlockStart:spacing.xSmall_8,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.xSmall_8,fontSize:font.body.size.xsmall}});
1776
+ const StartCoordsAngle=props=>{const{startCoords,allowReflexAngles,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??"",index===2?newLabel:pointLabels[2]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$d.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$d.equationBody,children:getAngleEquation(startCoords,allowReflexAngles)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1],startCoords[2]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Vertex",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value,startCoords[2]]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[2],onChange:value=>onChange([startCoords[0],startCoords[1],value]),pointLabel:pointLabels[2],onPointLabelChange:newLabel=>updatePointLabel(2,newLabel)})]})};const styles$d=StyleSheet.create({equationSection:{marginBlockStart:spacing.small_12},equationBody:{backgroundColor:semanticColor.core.background.neutral.subtle,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,marginBlockStart:spacing.xSmall_8,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.xSmall_8,fontSize:font.body.size.xsmall}});
1776
1777
 
1777
- const StartCoordsCircle=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=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$d.tile,children:[jsxRuntimeExports.jsxs(View,{style:styles$d.row,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",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(BodyText,{size:"medium",weight:"bold",tag:"label",style:styles$d.row,children:["Radius:",jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:radiusState,onChange:handleRadiuschange,style:styles$d.textField})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsxs(BodyText,{size:"medium",weight:"bold",tag:"span",style:styles$d.row,children:["Radius point label:",jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$d.textField,children:jsxRuntimeExports.jsx(TextField,{"aria-label":"Radius point name",value:pointLabels[0]??"",placeholder:"Radius point",onChange:newLabel=>onChangePointLabels([newLabel])})})]})]})};const styles$d=StyleSheet.create({tile:{backgroundColor:semanticColor.core.background.instructive.subtle,marginBlockStart:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1778
+ const StartCoordsCircle=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=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$c.tile,children:[jsxRuntimeExports.jsxs(View,{style:styles$c.row,children:[jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",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(BodyText,{size:"medium",weight:"bold",tag:"label",style:styles$c.row,children:["Radius:",jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:radiusState,onChange:handleRadiuschange,style:styles$c.textField})]}),jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsxs(BodyText,{size:"medium",weight:"bold",tag:"span",style:styles$c.row,children:["Radius point label:",jsxRuntimeExports.jsx(Strut,{size:spacing.small_12}),jsxRuntimeExports.jsx(View,{style:styles$c.textField,children:jsxRuntimeExports.jsx(TextField,{"aria-label":"Radius point name",value:pointLabels[0]??"",placeholder:"Radius point",onChange:newLabel=>onChangePointLabels([newLabel])})})]})]})};const styles$c=StyleSheet.create({tile:{backgroundColor:semanticColor.core.background.instructive.subtle,marginBlockStart:spacing.xSmall_8,padding:spacing.small_12,borderRadius:spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{width:spacing.xxxLarge_64}});
1778
1779
 
1779
- const AsymptoteInput=props=>{const{axis,value,onChange}=props;const[textState,setTextState]=React.useState(value.toString());React.useEffect(()=>{setTextState(value.toString());},[value]);function handleChange(newValue){setTextState(newValue);if(isNaN(+newValue)||newValue===""){return}onChange(parseFloat(newValue));}return jsxRuntimeExports.jsxs(BodyText,{weight:"bold",tag:"label",className:styles$f.tileRow,children:[`Asymptote ${axis} =`,jsxRuntimeExports.jsx(View,{className:styles$f["text-field-wrapper"],children:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:textState,onChange:handleChange})})]})};
1780
+ const AsymptoteInput=props=>{const{axis,value,onChange}=props;const[textState,setTextState]=React.useState(value.toString());React.useEffect(()=>{setTextState(value.toString());},[value]);function handleChange(newValue){setTextState(newValue);if(isNaN(+newValue)||newValue===""){return}onChange(parseFloat(newValue));}return jsxRuntimeExports.jsxs(BodyText,{weight:"bold",tag:"label",className:styles$e.tileRow,children:[`Asymptote ${axis} =`,jsxRuntimeExports.jsx(View,{className:styles$e["text-field-wrapper"],children:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:textState,onChange:handleChange})})]})};
1780
1781
 
1781
1782
  const StartCoordsExponential=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const{coords,asymptote}=startCoords;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:coords[0],onChange:value=>onChange({coords:[value,coords[1]],asymptote}),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:coords[1],onChange:value=>onChange({coords:[coords[0],value],asymptote}),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(AsymptoteInput,{axis:"y",value:asymptote,onChange:newY=>onChange({coords:[coords[0],coords[1]],asymptote:newY})})]})};
1782
1783
 
1783
1784
  const StartCoordsLine=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)})]})};
1784
1785
 
1785
- const StartCoordsLogarithm=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const{coords,asymptote}=startCoords;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$f.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{className:styles$f.equationBody,children:getLogarithmEquation(coords,asymptote)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:coords[0],onChange:value=>onChange({coords:[value,coords[1]],asymptote}),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:coords[1],onChange:value=>onChange({coords:[coords[0],value],asymptote}),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(AsymptoteInput,{axis:"x",value:asymptote,onChange:newX=>onChange({coords:[coords[0],coords[1]],asymptote:newX})})]})};
1786
+ const StartCoordsLogarithm=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const{coords,asymptote}=startCoords;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$e.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{className:styles$e.equationBody,children:getLogarithmEquation(coords,asymptote)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:coords[0],onChange:value=>onChange({coords:[value,coords[1]],asymptote}),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:coords[1],onChange:value=>onChange({coords:[coords[0],value],asymptote}),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(AsymptoteInput,{axis:"x",value:asymptote,onChange:newX=>onChange({coords:[coords[0],coords[1]],asymptote:newX})})]})};
1786
1787
 
1787
1788
  const StartCoordsMultiline=props=>{const{startCoords,type,onChange,pointLabels,onChangePointLabels}=props;const graphName=type==="segment"?"Segment":"Line";const updatePointLabel=(flatIndex,newLabel)=>{const totalPoints=startCoords.length*2;const next=Array.from({length:totalPoints},(_,i)=>i===flatIndex?newLabel:pointLabels[i]??"");onChangePointLabels(next);};return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:startCoords.map((coordPair,i)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(BodyText,{size:"medium",weight:"bold",tag:"span",children:`${graphName} ${i+1}`}),expanded:true,children:[jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:coordPair[0],onChange:value=>{const newCoords=[...startCoords];newCoords[i]=[value,coordPair[1]];onChange(newCoords);},pointLabel:pointLabels[i*2],onPointLabelChange:newLabel=>updatePointLabel(i*2,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:coordPair[1],onChange:value=>{const newCoords=[...startCoords];newCoords[i]=[coordPair[0],value];onChange(newCoords);},pointLabel:pointLabels[i*2+1],onPointLabelChange:newLabel=>updatePointLabel(i*2+1,newLabel)})]},`segment-${i}-start-coords`))})};
1788
1789
 
1789
1790
  const StartCoordsPoint=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:startCoords.map((coord,index)=>jsxRuntimeExports.jsx(CoordInput,{label:`Point ${index+1}`,coord:coord,onChange:newCoord=>{const newStartCoords=[...startCoords];newStartCoords[index]=newCoord;onChange(newStartCoords);},pointLabel:pointLabels?.[index],onPointLabelChange:onChangePointLabels&&(newLabel=>{const next=Array.from({length:startCoords.length},(_,i)=>i===index?newLabel:pointLabels?.[i]??"");onChangePointLabels(next);})},index))})};
1790
1791
 
1791
- const StartCoordsQuadratic=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??"",index===2?newLabel:pointLabels[2]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$c.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$c.equationBody,children:getQuadraticEquation(startCoords)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1],startCoords[2]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value,startCoords[2]]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 3",coord:startCoords[2],onChange:value=>onChange([startCoords[0],startCoords[1],value]),pointLabel:pointLabels[2],onPointLabelChange:newLabel=>updatePointLabel(2,newLabel)})]})};const styles$c=StyleSheet.create({equationSection:{marginBlockStart:spacing.small_12},equationBody:{backgroundColor:semanticColor.core.background.neutral.subtle,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,marginBlockStart:spacing.xSmall_8,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.xSmall_8,fontSize:font.body.size.xsmall}});
1792
+ const StartCoordsQuadratic=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??"",index===2?newLabel:pointLabels[2]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$b.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$b.equationBody,children:getQuadraticEquation(startCoords)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1],startCoords[2]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value,startCoords[2]]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 3",coord:startCoords[2],onChange:value=>onChange([startCoords[0],startCoords[1],value]),pointLabel:pointLabels[2],onPointLabelChange:newLabel=>updatePointLabel(2,newLabel)})]})};const styles$b=StyleSheet.create({equationSection:{marginBlockStart:spacing.small_12},equationBody:{backgroundColor:semanticColor.core.background.neutral.subtle,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,marginBlockStart:spacing.xSmall_8,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.xSmall_8,fontSize:font.body.size.xsmall}});
1792
1793
 
1793
- const StartCoordsSinusoid=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$b.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$b.equationBody,children:getSinusoidEquation(startCoords)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)})]})};const styles$b=StyleSheet.create({equationSection:{marginBlockStart:spacing.small_12},equationBody:{backgroundColor:semanticColor.core.background.neutral.subtle,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,marginBlockStart:spacing.xSmall_8,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.xSmall_8,fontSize:font.body.size.xsmall}});
1794
+ const StartCoordsSinusoid=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{style:styles$a.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{style:styles$a.equationBody,children:getSinusoidEquation(startCoords)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)})]})};const styles$a=StyleSheet.create({equationSection:{marginBlockStart:spacing.small_12},equationBody:{backgroundColor:semanticColor.core.background.neutral.subtle,border:`1px solid ${semanticColor.core.border.neutral.subtle}`,marginBlockStart:spacing.xSmall_8,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.xSmall_8,fontSize:font.body.size.xsmall}});
1794
1795
 
1795
- const StartCoordsTangent=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$f.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{className:styles$f.equationBody,children:getTangentEquation(startCoords)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)})]})};
1796
+ const StartCoordsTangent=props=>{const{startCoords,onChange,pointLabels,onChangePointLabels}=props;const updatePointLabel=(index,newLabel)=>{const next=[index===0?newLabel:pointLabels[0]??"",index===1?newLabel:pointLabels[1]??""];onChangePointLabels(next);};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(View,{className:styles$e.equationSection,children:[jsxRuntimeExports.jsx(BodyText,{children:"Starting equation:"}),jsxRuntimeExports.jsx(BodyMonospace,{className:styles$e.equationBody,children:getTangentEquation(startCoords)})]}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1]]),pointLabel:pointLabels[0],onPointLabelChange:newLabel=>updatePointLabel(0,newLabel)}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value]),pointLabel:pointLabels[1],onPointLabelChange:newLabel=>updatePointLabel(1,newLabel)})]})};
1796
1797
 
1797
1798
  const StartCoordsVector=props=>{const{startCoords,onChange}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(CoordInput,{label:"Point 1",coord:startCoords[0],onChange:value=>onChange([value,startCoords[1]])}),jsxRuntimeExports.jsx(CoordInput,{label:"Point 2",coord:startCoords[1],onChange:value=>onChange([startCoords[0],value])})]})};
1798
1799
 
1799
- const StartCoordsSettingsInner=props=>{const{type,range,step,allowReflexAngles,onChange,onChangePointLabels}=props;switch(type){case "absolute-value":const absoluteValueCoords=getAbsoluteValueCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsAbsoluteValue,{startCoords:absoluteValueCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "linear":case "ray":const linearCoords=getLineCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsLine,{startCoords:linearCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});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,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});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,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "sinusoid":const sinusoidCoords=getSinusoidCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsSinusoid,{startCoords:sinusoidCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "exponential":{const defaultStartCoords=getDefaultGraphStartCoords(props,range,step);const currentStartCoords=props.startCoords??defaultStartCoords;return jsxRuntimeExports.jsx(StartCoordsExponential,{startCoords:currentStartCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels})}case "logarithm":{const defaultLogarithmCoords=getDefaultGraphStartCoords(props,range,step);const currentLogarithmCoords=props.startCoords??defaultLogarithmCoords;return jsxRuntimeExports.jsx(StartCoordsLogarithm,{startCoords:currentLogarithmCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels})}case "vector":{const vectorCoords=getVectorCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsVector,{startCoords:vectorCoords,onChange:onChange})}case "tangent":const tangentCoords=getTangentCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsTangent,{startCoords:tangentCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "quadratic":const quadraticCoords=getQuadraticCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsQuadratic,{startCoords:quadraticCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "point":case "polygon":const pointCoords=type==="point"?getPointCoords(props,range,step):getPolygonCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsPoint,{startCoords:pointCoords,onChange:onChange,pointLabels:props.pointLabels,onChangePointLabels:onChangePointLabels});case "angle":const angleCoords=getAngleCoords({graph:props,range,step});return jsxRuntimeExports.jsx(StartCoordsAngle,{startCoords:angleCoords,allowReflexAngles:allowReflexAngles,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});default:return null}};const StartCoordsSettings=props=>{const{range,step,editingDisabled,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(View,{className:styles$f.resetButton,children:jsxRuntimeExports.jsx(Button,{startIcon:arrowCounterClockwise,kind:"tertiary",size:"small",disabled:editingDisabled,onClick:()=>{onChange(getDefaultGraphStartCoords(props,range,step));},children:"Use default start coordinates"})})]})]})};
1800
+ const StartCoordsSettingsInner=props=>{const{type,range,step,allowReflexAngles,onChange,onChangePointLabels}=props;switch(type){case "absolute-value":const absoluteValueCoords=getAbsoluteValueCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsAbsoluteValue,{startCoords:absoluteValueCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "linear":case "ray":const linearCoords=getLineCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsLine,{startCoords:linearCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});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,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});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,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "sinusoid":const sinusoidCoords=getSinusoidCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsSinusoid,{startCoords:sinusoidCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "exponential":{const defaultStartCoords=getDefaultGraphStartCoords(props,range,step);const currentStartCoords=props.startCoords??defaultStartCoords;return jsxRuntimeExports.jsx(StartCoordsExponential,{startCoords:currentStartCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels})}case "logarithm":{const defaultLogarithmCoords=getDefaultGraphStartCoords(props,range,step);const currentLogarithmCoords=props.startCoords??defaultLogarithmCoords;return jsxRuntimeExports.jsx(StartCoordsLogarithm,{startCoords:currentLogarithmCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels})}case "vector":{const vectorCoords=getVectorCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsVector,{startCoords:vectorCoords,onChange:onChange})}case "tangent":const tangentCoords=getTangentCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsTangent,{startCoords:tangentCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "quadratic":const quadraticCoords=getQuadraticCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsQuadratic,{startCoords:quadraticCoords,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});case "point":case "polygon":const pointCoords=type==="point"?getPointCoords(props,range,step):getPolygonCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsPoint,{startCoords:pointCoords,onChange:onChange,pointLabels:props.pointLabels,onChangePointLabels:onChangePointLabels});case "angle":const angleCoords=getAngleCoords({graph:props,range,step});return jsxRuntimeExports.jsx(StartCoordsAngle,{startCoords:angleCoords,allowReflexAngles:allowReflexAngles,onChange:onChange,pointLabels:props.pointLabels??[],onChangePointLabels:onChangePointLabels});default:return null}};const StartCoordsSettings=props=>{const{range,step,editingDisabled,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(View,{className:styles$e.resetButton,children:jsxRuntimeExports.jsx(Button,{startIcon:arrowCounterClockwise,kind:"tertiary",size:"small",disabled:editingDisabled,onClick:()=>{onChange(getDefaultGraphStartCoords(props,range,step));},children:"Use default start coordinates"})})]})]})};
1800
1801
 
1801
1802
  function toTrio(pointLabels){return [pointLabels[0]??"",pointLabels[1]??"",pointLabels[2]??""]}function toPair(pointLabels){return [pointLabels[0]??"",pointLabels[1]??""]}function toArray(pointLabels){return [...pointLabels]}function reshapePointLabelsForGraphType(pointLabels,graph,correct){if(!graph?.type||!correct){return null}let nextGraph;let nextCorrect=correct;switch(graph.type){case "angle":case "quadratic":{const reshaped=toTrio(pointLabels);nextGraph={...graph,pointLabels:reshaped};if(correct.type===graph.type){nextCorrect={...correct,pointLabels:reshaped};}break}case "absolute-value":case "linear":case "ray":{const reshaped=toPair(pointLabels);nextGraph={...graph,pointLabels:reshaped};if(correct.type===graph.type){nextCorrect={...correct,pointLabels:reshaped};}break}case "circle":case "exponential":case "linear-system":case "logarithm":case "point":case "polygon":case "segment":case "sinusoid":case "tangent":{const reshaped=toArray(pointLabels);nextGraph={...graph,pointLabels:reshaped};if(correct.type===graph.type){nextCorrect={...correct,pointLabels:reshaped};}break}case "vector":case "none":return null}return {graph:nextGraph,correct:nextCorrect}}
1802
1803
 
1803
- const InteractiveGraph=InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React.Component{serialize(){const json=_.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","showAxisArrows","showAxisTicks","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();_.extend(json,{graph:{type:correct.type,startCoords:getStartCoords(this.props.graph),..."pointLabels"in this.props.graph&&this.props.graph.pointLabels?{pointLabels:this.props.graph.pointLabels}:{},..."showPointLabels"in this.props.graph&&this.props.graph.showPointLabels?{showPointLabels:this.props.graph.showPointLabels}:{}},correct:correct});_.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(_.has(correct,key)){json.graph[key]=correct[key];}});}else {_.extend(json,{graph:this.props.graph,correct:this.props.correct});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const sizeClass=containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",options:{box:this.props.box,range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription},static:this.props.apiOptions?.editingDisabled??false,trackInteraction:function(){},userInput:this.props.static===true&&correct!=null&&"showPointLabels"in correct?{...correct,showPointLabels:false}:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant(newGraph!=null);if(this.props.static===true&&newGraph!=null&&"showPointLabels"in newGraph){newGraph={...newGraph,showPointLabels:"showPointLabels"in correct?correct.showPointLabels:undefined};}if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(Id,{children:graphId=>jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type",labelSize:"medium",children:jsxRuntimeExports.jsx(GraphTypeSelector,{disabled:this.props.apiOptions?.editingDisabled??false,graphType:this.props.graph?.type??"none",onChange:type=>{this.props.onChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsx(AngleAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:this.props.onChange}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),!this.props.static&&this.props.graph?.type&&this.props.graph.type!=="vector"&&this.props.graph.type!=="none"&&jsxRuntimeExports.jsx(ShowPointLabelsToggle,{showPointLabels:this.props.graph.showPointLabels===true,pointLabels:this.props.graph.pointLabels,onChange:this.changeShowPointLabels}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.changeStartCoords,onChangePointLabels:this.changePointLabels}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures,editingDisabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange,apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.changePointLabels=pointLabels=>{const next=reshapePointLabelsForGraphType(pointLabels,this.props.graph,this.props.correct);if(next){this.props.onChange(next);}},this.changeShowPointLabels=showPointLabels=>{const{graph,correct}=this.props;if(graph===undefined||correct===undefined){return}const newGraph=withShowPointLabels(graph,showPointLabels);const newCorrect=withShowPointLabels(correct,showPointLabels);if(newGraph===undefined||newCorrect===undefined){return}this.props.onChange({graph:newGraph,correct:newCorrect});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}if(this.props.graph?.type==="exponential"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteY=asymptote;const minY=Math.min(coords[0][1],coords[1][1]);const maxY=Math.max(coords[0][1],coords[1][1]);if(asymptoteY>=minY&&asymptoteY<=maxY){issues.push("The exponential start asymptote must not fall between or on the curve's start points.");}}if(this.props.graph?.type==="logarithm"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteX=asymptote;const minX=Math.min(coords[0][0],coords[1][0]);const maxX=Math.max(coords[0][0],coords[1][0]);if(asymptoteX>=minX&&asymptoteX<=maxX){issues.push("The logarithm start asymptote must not fall between or on the curve's start points.");}}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.bestPractices={url:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/3295281289/Interactive+Graph+Widget#Adding-a-new-Interactive-Graph-Widget",label:"Interactive Graph best practices"};InteractiveGraphEditor.defaultProps={...interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant(b.type==="angle");return {...a,...b};case "circle":invariant(b.type==="circle");return {...a,...b};case "linear":invariant(b.type==="linear");return {...a,...b};case "linear-system":invariant(b.type==="linear-system");return {...a,...b};case "none":invariant(b.type==="none");return {...a,...b};case "point":invariant(b.type==="point");return {...a,...b};case "polygon":invariant(b.type==="polygon");return {...a,...b};case "quadratic":invariant(b.type==="quadratic");return {...a,...b};case "ray":invariant(b.type==="ray");return {...a,...b};case "segment":invariant(b.type==="segment");return {...a,...b};case "sinusoid":invariant(b.type==="sinusoid");return {...a,...b};case "absolute-value":invariant(b.type==="absolute-value");return {...a,...b};case "exponential":invariant(b.type==="exponential");return {...a,...b};case "tangent":invariant(b.type==="tangent");return {...a,...b};case "logarithm":invariant(b.type==="logarithm");return {...a,...b};case "vector":invariant(b.type==="vector");return {...a,...b};default:throw new UnreachableCaseError(a)}}function withShowPointLabels(graph,showPointLabels){switch(graph.type){case "absolute-value":case "angle":case "circle":case "exponential":case "linear":case "linear-system":case "logarithm":case "point":case "polygon":case "quadratic":case "ray":case "segment":case "sinusoid":case "tangent":return {...graph,showPointLabels};case "none":case "vector":return undefined;default:throw new UnreachableCaseError(graph)}}
1804
+ const InteractiveGraph=InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React.Component{serialize(){const json=_.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","showAxisArrows","showAxisTicks","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();_.extend(json,{graph:{type:correct.type,startCoords:getStartCoords(this.props.graph),..."pointLabels"in this.props.graph&&this.props.graph.pointLabels?{pointLabels:this.props.graph.pointLabels}:{},..."showPointLabels"in this.props.graph&&this.props.graph.showPointLabels?{showPointLabels:this.props.graph.showPointLabels}:{}},correct:correct});_.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(_.has(correct,key)){json.graph[key]=correct[key];}});}else {_.extend(json,{graph:this.props.graph,correct:this.props.correct});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const sizeClass=containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",options:{box:this.props.box,range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription},static:this.props.apiOptions?.editingDisabled??false,trackInteraction:function(){},userInput:this.props.static===true&&correct!=null&&"showPointLabels"in correct?{...correct,showPointLabels:false}:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant(newGraph!=null);if(this.props.static===true&&newGraph!=null&&"showPointLabels"in newGraph){newGraph={...newGraph,showPointLabels:"showPointLabels"in correct?correct.showPointLabels:undefined};}if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(Id,{children:graphId=>jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type",labelSize:"medium",children:jsxRuntimeExports.jsx(GraphTypeSelector,{disabled:this.props.apiOptions?.editingDisabled??false,graphType:this.props.graph?.type??"none",onChange:type=>{this.props.onChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsx(AngleAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:this.props.onChange}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),!this.props.static&&this.props.graph?.type&&this.props.graph.type!=="vector"&&this.props.graph.type!=="none"&&jsxRuntimeExports.jsx(ShowPointLabelsToggle,{showPointLabels:this.props.graph.showPointLabels===true,pointLabels:this.props.graph.pointLabels,onChange:this.changeShowPointLabels}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:this.changeStartCoords,onChangePointLabels:this.changePointLabels}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures,editingDisabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange,apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.changePointLabels=pointLabels=>{const next=reshapePointLabelsForGraphType(pointLabels,this.props.graph,this.props.correct);if(next){this.props.onChange(next);}},this.changeShowPointLabels=showPointLabels=>{const{graph,correct}=this.props;if(graph===undefined||correct===undefined){return}const newGraph=withShowPointLabels(graph,showPointLabels);const newCorrect=withShowPointLabels(correct,showPointLabels);if(newGraph===undefined||newCorrect===undefined){return}this.props.onChange({graph:newGraph,correct:newCorrect});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}if(this.props.graph?.type==="exponential"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteY=asymptote;const minY=Math.min(coords[0][1],coords[1][1]);const maxY=Math.max(coords[0][1],coords[1][1]);if(asymptoteY>=minY&&asymptoteY<=maxY){issues.push("The exponential start asymptote must not fall between or on the curve's start points.");}}if(this.props.graph?.type==="logarithm"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteX=asymptote;const minX=Math.min(coords[0][0],coords[1][0]);const maxX=Math.max(coords[0][0],coords[1][0]);if(asymptoteX>=minX&&asymptoteX<=maxX){issues.push("The logarithm start asymptote must not fall between or on the curve's start points.");}}return issues};}}InteractiveGraphEditor.bestPractices={url:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/3295281289/Interactive+Graph+Widget#Adding-a-new-Interactive-Graph-Widget",label:"Interactive Graph best practices"};InteractiveGraphEditor.defaultProps={...interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant(b.type==="angle");return {...a,...b};case "circle":invariant(b.type==="circle");return {...a,...b};case "linear":invariant(b.type==="linear");return {...a,...b};case "linear-system":invariant(b.type==="linear-system");return {...a,...b};case "none":invariant(b.type==="none");return {...a,...b};case "point":invariant(b.type==="point");return {...a,...b};case "polygon":invariant(b.type==="polygon");return {...a,...b};case "quadratic":invariant(b.type==="quadratic");return {...a,...b};case "ray":invariant(b.type==="ray");return {...a,...b};case "segment":invariant(b.type==="segment");return {...a,...b};case "sinusoid":invariant(b.type==="sinusoid");return {...a,...b};case "absolute-value":invariant(b.type==="absolute-value");return {...a,...b};case "exponential":invariant(b.type==="exponential");return {...a,...b};case "tangent":invariant(b.type==="tangent");return {...a,...b};case "logarithm":invariant(b.type==="logarithm");return {...a,...b};case "vector":invariant(b.type==="vector");return {...a,...b};default:throw new UnreachableCaseError(a)}}function withShowPointLabels(graph,showPointLabels){switch(graph.type){case "absolute-value":case "angle":case "circle":case "exponential":case "linear":case "linear-system":case "logarithm":case "point":case "polygon":case "quadratic":case "ray":case "segment":case "sinusoid":case "tangent":return {...graph,showPointLabels};case "none":case "vector":return undefined;default:throw new UnreachableCaseError(graph)}}
1804
1805
 
1805
- const gray98="#FAFAFA";const gray95="#F0F1F2";const gray85="#D6D8DA";const gray76="#BABEC2";const gray68="#888D93";const gray41="#626569";const gray17="#21242C";
1806
+ const gray68="#888D93";const gray41="#626569";
1806
1807
 
1807
- class FormWrappedTextField extends React.Component{render(){const{forwardedRef,width,grow,shrink,icon,backgroundColor,focusBorderColor,borderColor,color,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){extraStyles.color=color;}const borderColorStyle=focused?focusBorderColor||semanticColor.focus.outer:borderColor||semanticColor.core.border.neutral.subtle;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",marginBlockEnd:0,paddingInlineStart: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",paddingBlock:"8px",paddingInline:"10px"},container:{display:"inline-flex",alignItems:"center",marginBlockEnd:0},defaultBackground:{backgroundColor:semanticColor.core.background.base.default},icon:{display:"flex",alignItems:"center",justifyContent:"center"}});var FormWrappedTextField$1 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(FormWrappedTextField,{...props,forwardedRef:ref}));
1808
+ class FormWrappedTextField extends React.Component{render(){const{forwardedRef,width,grow,shrink,icon,backgroundColor,focusBorderColor,borderColor,color,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){extraStyles.color=color;}const borderColorStyle=focused?focusBorderColor||semanticColor.focus.outer:borderColor||semanticColor.core.border.neutral.subtle;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",marginBlockEnd:0,paddingInlineStart: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",paddingBlock:"8px",paddingInline:"10px"},container:{display:"inline-flex",alignItems:"center",marginBlockEnd:0},defaultBackground:{backgroundColor:semanticColor.core.background.base.default},icon:{display:"flex",alignItems:"center",justifyContent:"center"}});var FormWrappedTextField$1 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(FormWrappedTextField,{...props,forwardedRef:ref}));
1808
1809
 
1809
- var styles$9 = {"answers":"perseus_DTFHZTRU","answer":"perseus_h6UVAo1f","addAnswerContent":"perseus_bB9KRsBQ","addAnswer":"perseus_be-n-Bce","removeButtonContent":"perseus_JqR-dZ9h","removeButton":"perseus_uYELsWW-"};
1810
+ var styles$8 = {"answers":"perseus_DTFHZTRU","answer":"perseus_h6UVAo1f","addAnswerContent":"perseus_bB9KRsBQ","addAnswer":"perseus_be-n-Bce","removeButtonContent":"perseus_JqR-dZ9h","removeButton":"perseus_uYELsWW-"};
1810
1811
 
1811
- const AddAnswer=({onClick,editingDisabled})=>jsxRuntimeExports.jsx(Clickable,{className:styles$9.addAnswer,disabled:editingDisabled,onClick:onClick,children:()=>jsxRuntimeExports.jsxs("span",{className:styles$9.addAnswerContent,children:[jsxRuntimeExports.jsx(PhosphorIcon,{icon:plusCircle,size:"medium","aria-hidden":true}),jsxRuntimeExports.jsx(BodyText,{tag:"span",size:"medium",weight:"bold",children:"Add an answer choice"})]})});const Answer=({answer,onChange,onRemove,editingDisabled})=>jsxRuntimeExports.jsxs("li",{className:styles$9.answer,children:[jsxRuntimeExports.jsx(Clickable,{className:styles$9.removeButton,"aria-label":"Remove answer",onClick:onRemove,disabled:editingDisabled,children:()=>jsxRuntimeExports.jsx("span",{className:styles$9.removeButtonContent,children:jsxRuntimeExports.jsx(PhosphorIcon,{icon:minusCircle,size:"medium","aria-hidden":true})})}),jsxRuntimeExports.jsx(FormWrappedTextField$1,{grow:1,onChange:e=>onChange(e.target.value),value:answer})]});const AnswerChoices=({choices,editingDisabled,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:"Answer Choices"}),jsxRuntimeExports.jsx("ul",{className:styles$9.answers,children:choices.map((answer,index)=>jsxRuntimeExports.jsx(Answer,{answer:answer,editingDisabled:editingDisabled,onChange:answer=>{if(editingDisabled){return}onChange([...choices.slice(0,index),answer,...choices.slice(index+1)]);},onRemove:()=>{if(editingDisabled){return}onChange([...choices.slice(0,index),...choices.slice(index+1)]);}},index))}),jsxRuntimeExports.jsx(AddAnswer,{editingDisabled:editingDisabled,onClick:()=>{if(editingDisabled){return}onChange([...choices,""]);}})]});
1812
+ const AddAnswer=({onClick,editingDisabled})=>jsxRuntimeExports.jsx(Clickable,{className:styles$8.addAnswer,disabled:editingDisabled,onClick:onClick,children:()=>jsxRuntimeExports.jsxs("span",{className:styles$8.addAnswerContent,children:[jsxRuntimeExports.jsx(PhosphorIcon,{icon:plusCircle,size:"medium","aria-hidden":true}),jsxRuntimeExports.jsx(BodyText,{tag:"span",size:"medium",weight:"bold",children:"Add an answer choice"})]})});const Answer=({answer,onChange,onRemove,editingDisabled})=>jsxRuntimeExports.jsxs("li",{className:styles$8.answer,children:[jsxRuntimeExports.jsx(Clickable,{className:styles$8.removeButton,"aria-label":"Remove answer",onClick:onRemove,disabled:editingDisabled,children:()=>jsxRuntimeExports.jsx("span",{className:styles$8.removeButtonContent,children:jsxRuntimeExports.jsx(PhosphorIcon,{icon:minusCircle,size:"medium","aria-hidden":true})})}),jsxRuntimeExports.jsx(FormWrappedTextField$1,{grow:1,onChange:e=>onChange(e.target.value),value:answer})]});const AnswerChoices=({choices,editingDisabled,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:"Answer Choices"}),jsxRuntimeExports.jsx("ul",{className:styles$8.answers,children:choices.map((answer,index)=>jsxRuntimeExports.jsx(Answer,{answer:answer,editingDisabled:editingDisabled,onChange:answer=>{if(editingDisabled){return}onChange([...choices.slice(0,index),answer,...choices.slice(index+1)]);},onRemove:()=>{if(editingDisabled){return}onChange([...choices.slice(0,index),...choices.slice(index+1)]);}},index))}),jsxRuntimeExports.jsx(AddAnswer,{editingDisabled:editingDisabled,onClick:()=>{if(editingDisabled){return}onChange([...choices,""]);}})]});
1812
1813
 
1813
1814
  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};
1814
1815
 
1815
- 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$8.container,focused&&styles$8.focused),style:style,"data-testid":dataTestId,"data-checked":checked,children:[jsxRuntimeExports.jsx("svg",{className:css(styles$8.svg,(disabled||appearDisabled)&&styles$8.disabled),width:sizeWithPadding,height:sizeWithPadding,viewBox:`-${padding} -${padding}
1816
- ${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:semanticColor.core.foreground.knockout.default,stroke:semanticColor.core.foreground.knockout.default,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:semanticColor.core.foreground.knockout.default,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$8.checkbox,disabled&&styles$8.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$8=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",insetBlockStart:-2,insetInlineEnd:-2,insetBlockEnd:-2,insetInlineStart:-2,borderRadius:borderRadius+2,backgroundColor:"lightblue"}},svg:{position:"absolute",insetInlineStart:0,insetBlockStart:0},checkbox:{appearance:"none",opacity:0,position:"absolute",insetBlockStart:padding,width:size,height:size,margin:0,outline:"none",cursor:"pointer"},disabled:{opacity:.5},defaultCursor:{cursor:"default"}});
1816
+ 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}
1817
+ ${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:semanticColor.core.foreground.knockout.default,stroke:semanticColor.core.foreground.knockout.default,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:semanticColor.core.foreground.knockout.default,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",insetBlockStart:-2,insetInlineEnd:-2,insetBlockEnd:-2,insetInlineStart:-2,borderRadius:borderRadius+2,backgroundColor:"lightblue"}},svg:{position:"absolute",insetInlineStart:0,insetBlockStart:0},checkbox:{appearance:"none",opacity:0,position:"absolute",insetBlockStart:padding,width:size,height:size,margin:0,outline:"none",cursor:"pointer"},disabled:{opacity:.5},defaultCursor:{cursor:"default"}});
1817
1818
 
1818
- var styles$7 = {"optionsList":"perseus_9p2fIJDN","option":"perseus_uz5HIc6B","label":"perseus_nqkpIulz","selectLabel":"perseus_aAJcd7Pn","editor":"perseus_ELq9XmxW"};
1819
+ var styles$6 = {"optionsList":"perseus_9p2fIJDN","option":"perseus_uz5HIc6B","label":"perseus_nqkpIulz","selectLabel":"perseus_aAJcd7Pn","editor":"perseus_ELq9XmxW"};
1819
1820
 
1820
- const Behavior=({multipleAnswers,hideChoicesFromInstructions,preferredPopoverDirection,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:"Behavior"}),jsxRuntimeExports.jsxs("ul",{className:styles$7.optionsList,children:[jsxRuntimeExports.jsxs("li",{className:styles$7.option,children:[jsxRuntimeExports.jsx(Checkbox,{checked:multipleAnswers,onChange:()=>onChange({multipleAnswers:!multipleAnswers})}),jsxRuntimeExports.jsx("span",{className:styles$7.label,children:"Allow multiple answers per marker"})]}),jsxRuntimeExports.jsxs("li",{className:styles$7.option,children:[jsxRuntimeExports.jsx(Checkbox,{checked:hideChoicesFromInstructions,onChange:()=>onChange({hideChoicesFromInstructions:!hideChoicesFromInstructions})}),jsxRuntimeExports.jsx("span",{className:styles$7.label,children:"Do not display answer choices in instructions"})]}),jsxRuntimeExports.jsxs("li",{className:styles$7.option,children:[jsxRuntimeExports.jsx("span",{className:[styles$7.label,styles$7.selectLabel].join(" "),children:"Preferred pop-over direction"}),jsxRuntimeExports.jsxs("select",{value:preferredPopoverDirection,onChange:e=>{onChange({preferredPopoverDirection:e.target.value});},children:[jsxRuntimeExports.jsx("option",{value:"NONE",children:" No Preference "}),jsxRuntimeExports.jsx("option",{value:"UP",children:" Up "}),jsxRuntimeExports.jsx("option",{value:"DOWN",children:" Down "}),jsxRuntimeExports.jsx("option",{value:"LEFT",children:" Left "}),jsxRuntimeExports.jsx("option",{value:"RIGHT",children:" Right "})]})]})]})]});
1821
+ const Behavior=({multipleAnswers,hideChoicesFromInstructions,preferredPopoverDirection,onChange})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:"Behavior"}),jsxRuntimeExports.jsxs("ul",{className:styles$6.optionsList,children:[jsxRuntimeExports.jsxs("li",{className:styles$6.option,children:[jsxRuntimeExports.jsx(Checkbox,{checked:multipleAnswers,onChange:()=>onChange({multipleAnswers:!multipleAnswers})}),jsxRuntimeExports.jsx("span",{className:styles$6.label,children:"Allow multiple answers per marker"})]}),jsxRuntimeExports.jsxs("li",{className:styles$6.option,children:[jsxRuntimeExports.jsx(Checkbox,{checked:hideChoicesFromInstructions,onChange:()=>onChange({hideChoicesFromInstructions:!hideChoicesFromInstructions})}),jsxRuntimeExports.jsx("span",{className:styles$6.label,children:"Do not display answer choices in instructions"})]}),jsxRuntimeExports.jsxs("li",{className:styles$6.option,children:[jsxRuntimeExports.jsx("span",{className:[styles$6.label,styles$6.selectLabel].join(" "),children:"Preferred pop-over direction"}),jsxRuntimeExports.jsxs("select",{value:preferredPopoverDirection,onChange:e=>{onChange({preferredPopoverDirection:e.target.value});},children:[jsxRuntimeExports.jsx("option",{value:"NONE",children:" No Preference "}),jsxRuntimeExports.jsx("option",{value:"UP",children:" Up "}),jsxRuntimeExports.jsx("option",{value:"DOWN",children:" Down "}),jsxRuntimeExports.jsx("option",{value:"LEFT",children:" Left "}),jsxRuntimeExports.jsx("option",{value:"RIGHT",children:" Right "})]})]})]})]});
1821
1822
 
1822
- const{Icon}=components;const findAndFocusElement=component=>{const DOMNode=ReactDOM.findDOMNode(component);const button=DOMNode;if(button.focus){focusWithChromeStickyFocusBugWorkaround(button);}};const check=`M10,3.8C10,4,9.9,4.2,9.8,4.3L5.1,8.9L4.3,9.8C4.2,9.9,4,10,3.8,10
1823
- 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
1824
- 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
1825
- -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,
1826
- 10,3.8z`;const optionHeight=30;class Option extends React.Component{handleKeyDown(event){const{onDropdownClose}=this.props;const pressedKey=event.key;const focusedElement=event.currentTarget;if(pressedKey==="ArrowDown"&&focusedElement.nextElementSibling){event.preventDefault();focusedElement.nextElementSibling.focus();}if(pressedKey==="ArrowUp"&&focusedElement.previousElementSibling){event.preventDefault();focusedElement.previousElementSibling.focus();}if(pressedKey==="ArrowUp"&&!focusedElement.previousElementSibling&&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$6.notAButton,disabled&&styles$6.cursorDefault,hideFocusState&&styles$6.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$6.option,selected&&styles$6.optionSelected,disabled&&styles$6.optionDisabled),children:[children,selected&&jsxRuntimeExports.jsx("span",{className:css(styles$6.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$6.optionGroup,noMargin&&styles$6.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$6=StyleSheet.create({optionGroup:{marginBlock:"4px",marginInline:"0"},optionGroupNoMargin:{margin:0},option:{display:"flex",flexDirection:"row",alignItems:"center",paddingInlineStart:32,paddingInlineEnd: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",insetInlineStart:11},notAButton:{backgroundColor:"transparent",border:"none",display:"block",padding:0,margin:0,width:"100%",font:"inherit"},noFocus:{outline:"none"},cursorDefault:{cursor:"default"}});
1827
-
1828
- 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.updateAnswers(filteredAnswers));}}componentWillUnmount(){document.removeEventListener("click",this.handleClick,true);}openDropdown(){this.setState({showDropdown:true});}updateAnswers(answers){const{label,onChange,x,y}=this.props;onChange({answers,label,x,y});}updateLabel(label){const{answers,onChange,x,y}=this.props;onChange({answers,label,x,y});}render(){const{answers,choices,label,onRemove,x,y}=this.props;const{showDropdown}=this.state;return jsxRuntimeExports.jsx("div",{className:css(styles$5.marker,answers.length>0&&styles$5.markerWithAnswers,showDropdown&&styles$5.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$5.dropdownBody,styles$5.dropdownPositionWithArrow),children:[jsxRuntimeExports.jsx(Option,{value:"",onClick:()=>onRemove(),children:"Delete marker"}),jsxRuntimeExports.jsx("hr",{className:css(styles$5.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$5.labelContainer),children:jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"ARIA label (for screen readers)",onChange:this.handleLabelChange,value:label,width:"100%"})})]})})})}constructor(...args){super(...args),this.state={showDropdown:false},this.handleClick=e=>{const{showDropdown}=this.state;if(this._marker===e.target){this.setState({showDropdown:!showDropdown});}else if(showDropdown){if(this._marker&&e.target instanceof Node&&!this._marker.contains(e.target)){e.stopPropagation();this.setState({showDropdown:false});}}},this.handleLabelChange=e=>{this.updateLabel(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.updateAnswers(answers);};}}const styles$5=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,marginInlineStart:2,marginBlockStart: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,borderInlineEnd:`solid 16px ${gray98}`,borderBlockStart:"solid 16px transparent",borderBlockEnd:"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,maxBlockSize:320,cursor:"pointer"}});
1823
+ const Marker=React.forwardRef(function Marker({answers,choices,label,onChange,onRemove,x,y},ref){const[showDropdown,setShowDropdown]=React.useState(false);React.useImperativeHandle(ref,()=>({openDropdown:()=>setShowDropdown(true)}),[]);function updateAnswers(answers){onChange({answers,label,x,y});}React.useEffect(()=>{const filteredAnswers=answers.filter(answer=>choices.includes(answer));if(JSON.stringify(answers)!==JSON.stringify(filteredAnswers)){updateAnswers(filteredAnswers);}});function handleToggleAnswer(selectedValues){const values=Array.isArray(selectedValues)?selectedValues:[selectedValues];updateAnswers(values.filter(value=>value!=null));}function handleLabelChange(value){onChange({answers,label:value,x,y});}return jsxRuntimeExports.jsx(Popover,{opened:showDropdown,onClose:()=>setShowDropdown(false),dismissEnabled:true,content:jsxRuntimeExports.jsxs(PopoverContentCore,{style:styles$5.dropdownBody,children:[jsxRuntimeExports.jsx("div",{className:css(styles$5.labelContainer),children:jsxRuntimeExports.jsx(TextField,{placeholder:"ARIA label (for screen readers)",onChange:handleLabelChange,value:label})}),jsxRuntimeExports.jsx("hr",{className:css(styles$5.dividerHorizontal)}),jsxRuntimeExports.jsx(Listbox,{"aria-label":"Answer choices",onChange:handleToggleAnswer,selectionType:"multiple",value:answers,children:choices.map(choice=>jsxRuntimeExports.jsx(OptionItem,{value:choice,label:choice},choice))}),jsxRuntimeExports.jsx("hr",{className:css(styles$5.dividerHorizontal)}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",actionType:"destructive",onClick:onRemove,children:"Delete marker"})]}),children:()=>jsxRuntimeExports.jsx("button",{type:"button","aria-label":label?`Edit marker: ${label}`:"Edit unlabeled marker",className:css(styles$5.marker,answers.length>0&&styles$5.markerWithAnswers,showDropdown&&styles$5.markerSelected),onClick:()=>setShowDropdown(opened=>!opened),style:{left:`${x}%`,top:`${y}%`}})})});const styles$5=StyleSheet.create({marker:{position:"absolute",appearance:"none",padding:0,boxSizing:"content-box",width:sizing.size_160,height:sizing.size_160,transform:"translate(-50%, -50%)",cursor:"pointer",background:"linear-gradient(to bottom, rgba(33, 36, 44, 0.2), rgba(33, 36, 44, 0.5))",border:`solid 2px ${semanticColor.core.background.base.default}`,borderRadius:sizing.size_160,boxShadow:"0 2px 10px 0 rgba(33, 36, 44, 0.1)"},markerSelected:{width:sizing.size_280,height:sizing.size_280,border:"none",borderRadius:sizing.size_280,"::before":{content:"''",display:"block",width:sizing.size_200,height:sizing.size_200,marginInlineStart:sizing.size_020,border:`solid 2px ${semanticColor.core.background.base.default}`,borderRadius:sizing.size_200}},markerWithAnswers:{background:semanticColor.core.background.instructive.default},labelContainer:{padding:sizing.size_060},dividerHorizontal:{height:0,margin:0,border:`solid ${semanticColor.core.border.neutral.default}`,borderWidth:"0 0 1px",boxShadow:"none"},dropdownBody:{padding:0}});
1829
1824
 
1830
1825
  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(BodyText,{weight:"bold",tag:"span",children:"Markers"}),jsxRuntimeExports.jsx("div",{className:css(styles$4.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$4.markersCanvas),style:{maxInlineSize:imageWidth,maxBlockSize:imageHeight},children:[jsxRuntimeExports.jsx("img",{alt:"",className:css(styles$4.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();if(this.props.editingDisabled){return}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$4=StyleSheet.create({subtitle:{fontFamily:"inherit",fontSize:12,lineHeight:"14px",marginBlockStart:8,marginBlockEnd:12,color:gray68},markersCanvas:{position:"relative",border:"solid 1px rgba(33, 36, 44, 0.16)"},image:{display:"block",maxInlineSize:"100%"}});
1831
1826
 
@@ -1833,23 +1828,23 @@ var styles$3 = {"imageRow":"perseus_-XexOs6i"};
1833
1828
 
1834
1829
  const SelectImage=({onChange,url,editingDisabled=false})=>jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(BodyText,{weight:"bold",tag:"span",children:"Image"}),jsxRuntimeExports.jsxs("div",{className:styles$3.imageRow,children:[jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"URL",grow:1,onChange:e=>onChange(e.target.value),value:url}),jsxRuntimeExports.jsx(Button,{disabled:!url||editingDisabled,"aria-label":url?"":"Not implemented. Use the 'Add Image' button in "+"the editor to upload image, then copy the URL here.",onClick:()=>onChange(""),style:{minInlineSize:90},children:url?"Remove":"Upload"})]})]});
1835
1830
 
1836
- 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,preferredPopoverDirection}=this.props;const editingDisabled=this.props.apiOptions?.editingDisabled??false;const imageSelected=imageUrl&&imageWidth>0&&imageHeight>0;return jsxRuntimeExports.jsxs("div",{className:styles$7.editor,children:[jsxRuntimeExports.jsx(SelectImage,{onChange:this.handleImageChange,url:imageUrl,editingDisabled:editingDisabled}),imageSelected&&jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"Alt text (for screen readers)",onChange:e=>this.handleAltChange(e.target.value),value:imageAlt,width:"100%"}),jsxRuntimeExports.jsx(QuestionMarkers,{editingDisabled:editingDisabled,choices:choices,imageUrl:imageSelected?imageUrl:"",imageWidth:imageWidth,imageHeight:imageHeight,markers:markers,onChange:this.handleMarkersChange,ref:node=>this._questionMarkers=node}),jsxRuntimeExports.jsx(AnswerChoices,{choices:choices,editingDisabled:editingDisabled,onChange:this.handleChoicesChange}),jsxRuntimeExports.jsx(Behavior,{preferredPopoverDirection:preferredPopoverDirection,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)=>{if(this.props.imageUrl===url&&this.props.imageWidth===width&&this.props.imageHeight===height){return}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";
1831
+ 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,preferredPopoverDirection}=this.props;const editingDisabled=this.props.apiOptions?.editingDisabled??false;const imageSelected=imageUrl&&imageWidth>0&&imageHeight>0;return jsxRuntimeExports.jsxs("div",{className:styles$6.editor,children:[jsxRuntimeExports.jsx(SelectImage,{onChange:this.handleImageChange,url:imageUrl,editingDisabled:editingDisabled}),imageSelected&&jsxRuntimeExports.jsx(FormWrappedTextField$1,{placeholder:"Alt text (for screen readers)",onChange:e=>this.handleAltChange(e.target.value),value:imageAlt,width:"100%"}),jsxRuntimeExports.jsx(QuestionMarkers,{editingDisabled:editingDisabled,choices:choices,imageUrl:imageSelected?imageUrl:"",imageWidth:imageWidth,imageHeight:imageHeight,markers:markers,onChange:this.handleMarkersChange,ref:node=>this._questionMarkers=node}),jsxRuntimeExports.jsx(AnswerChoices,{choices:choices,editingDisabled:editingDisabled,onChange:this.handleChoicesChange}),jsxRuntimeExports.jsx(Behavior,{preferredPopoverDirection:preferredPopoverDirection,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)=>{if(this.props.imageUrl===url&&this.props.imageWidth===width&&this.props.imageHeight===height){return}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;
1837
1832
 
1838
- class MatcherEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-matcher-editor",children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip,{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,{options:this.props.left,onChange:options=>{this.props.onChange({left:options});},layout:"vertical"}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.right,onChange:options=>{this.props.onChange({right:options});},layout:"vertical"})]}),jsxRuntimeExports.jsxs("span",{children:[" ","Labels:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"These are entirely optional."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("input",{type:"text",defaultValue:this.props.labels[0],onChange:e=>{this.onLabelChange(0,e);}}),jsxRuntimeExports.jsx("input",{type:"text",defaultValue:this.props.labels[1],onChange:e=>{this.onLabelChange(1,e);}})]}),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,{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,{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=[...this.props.labels];labels[index]=e.target.value;this.props.onChange({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 {left:this.props.left,right:this.props.right,labels:this.props.labels,orderMatters:this.props.orderMatters,padding:this.props.padding}};}}MatcherEditor.widgetName="matcher";MatcherEditor.defaultProps=matcherLogic.defaultWidgetOptions;
1833
+ class MatcherEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-matcher-editor",children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip,{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,{options:this.props.left,onChange:options=>{this.props.onChange({left:options});},layout:"vertical"}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.right,onChange:options=>{this.props.onChange({right:options});},layout:"vertical"})]}),jsxRuntimeExports.jsxs("span",{children:[" ","Labels:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"These are entirely optional."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("input",{type:"text",defaultValue:this.props.labels[0],onChange:e=>{this.onLabelChange(0,e);}}),jsxRuntimeExports.jsx("input",{type:"text",defaultValue:this.props.labels[1],onChange:e=>{this.onLabelChange(1,e);}})]}),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,{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,{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=[...this.props.labels];labels[index]=e.target.value;this.props.onChange({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 {left:this.props.left,right:this.props.right,labels:this.props.labels,orderMatters:this.props.orderMatters,padding:this.props.padding}};}}MatcherEditor.defaultProps=matcherLogic.defaultWidgetOptions;
1839
1834
 
1840
- const{RangeInput: RangeInput$3}=components;const Matrix=MatrixWidget.widget;const MAX_BOARD_SIZE=6;class MatrixEditor extends React.Component{render(){const{matrixBoardSize,prefix,suffix,answers}=this.props;const matrixProps={onBlur:()=>{},onFocus:()=>{},trackInteraction:()=>{},userInput:{answers:answers.map(row=>row.map(cell=>cell==null?"":String(cell)))},handleUserInput:userInput=>{this.change({answers:userInput.answers});},...this.props,options:{matrixBoardSize,prefix,suffix}};return jsxRuntimeExports.jsxs("div",{className:"perseus-matrix-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[" ","Max matrix size:"," ",jsxRuntimeExports.jsx(RangeInput$3,{value:this.props.matrixBoardSize,onChange:this.onMatrixBoardSizeChange,useArrowKeys:true})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Matrix,{...matrixProps})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[" ","Matrix prefix:"," ",jsxRuntimeExports.jsx(Editor,{ref:"prefix",apiOptions:this.props.apiOptions,content:this.props.prefix,widgetEnabled:false,onChange:newProps=>{this.change({prefix:newProps.content});}})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[" ","Matrix suffix:"," ",jsxRuntimeExports.jsx(Editor,{ref:"suffix",apiOptions:this.props.apiOptions,content:this.props.suffix,widgetEnabled:false,onChange:newProps=>{this.change({suffix:newProps.content});}})]})]})}constructor(...args){super(...args),this.change=(...args)=>{if(this.props.apiOptions.editingDisabled){return}return deprecatedChangeableChange.apply(this,args)},this.onMatrixBoardSizeChange=range=>{const matrixSize=getMatrixSize(this.props.answers);if(range[0]!==null&&range[1]!==null){range=[Math.round(Math.min(Math.max(range[0],1),MAX_BOARD_SIZE)),Math.round(Math.min(Math.max(range[1],1),MAX_BOARD_SIZE))];const answers=_(Math.min(range[0],matrixSize[0])).times(row=>{return _(Math.min(range[1],matrixSize[1])).times(col=>{return this.props.answers[row][col]})});this.props.onChange({matrixBoardSize:range,answers:answers});}},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}MatrixEditor.widgetName="matrix";MatrixEditor.defaultProps=matrixLogic.defaultWidgetOptions;
1835
+ const{RangeInput: RangeInput$3}=components;const Matrix=MatrixWidget.widget;const MAX_BOARD_SIZE=6;class MatrixEditor extends React.Component{render(){const{matrixBoardSize,prefix,suffix,answers}=this.props;const matrixProps={onBlur:()=>{},onFocus:()=>{},trackInteraction:()=>{},userInput:{answers:answers.map(row=>row.map(cell=>cell==null?"":String(cell)))},handleUserInput:userInput=>{this.change({answers:userInput.answers});},...this.props,options:{matrixBoardSize,prefix,suffix}};return jsxRuntimeExports.jsxs("div",{className:"perseus-matrix-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[" ","Max matrix size:"," ",jsxRuntimeExports.jsx(RangeInput$3,{value:this.props.matrixBoardSize,onChange:this.onMatrixBoardSizeChange,useArrowKeys:true})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(Matrix,{...matrixProps})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[" ","Matrix prefix:"," ",jsxRuntimeExports.jsx(Editor,{ref:"prefix",apiOptions:this.props.apiOptions,content:this.props.prefix,widgetEnabled:false,onChange:newProps=>{this.change({prefix:newProps.content});}})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[" ","Matrix suffix:"," ",jsxRuntimeExports.jsx(Editor,{ref:"suffix",apiOptions:this.props.apiOptions,content:this.props.suffix,widgetEnabled:false,onChange:newProps=>{this.change({suffix:newProps.content});}})]})]})}constructor(...args){super(...args),this.change=(...args)=>{if(this.props.apiOptions.editingDisabled){return}return deprecatedChangeableChange.apply(this,args)},this.onMatrixBoardSizeChange=range=>{const matrixSize=getMatrixSize(this.props.answers);if(range[0]!==null&&range[1]!==null){range=[Math.round(Math.min(Math.max(range[0],1),MAX_BOARD_SIZE)),Math.round(Math.min(Math.max(range[1],1),MAX_BOARD_SIZE))];const answers=_(Math.min(range[0],matrixSize[0])).times(row=>{return _(Math.min(range[1],matrixSize[1])).times(col=>{return this.props.answers[row][col]})});this.props.onChange({matrixBoardSize:range,answers:answers});}},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}MatrixEditor.defaultProps=matrixLogic.defaultWidgetOptions;
1841
1836
 
1842
- const{NumberInput: NumberInput$4,RangeInput: RangeInput$2}=components;const defaultImage={url:null,top:0,left:0};class MeasurerEditor extends React.Component{render(){const image=_.extend({},defaultImage,this.props.image);return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-measurer",children:[jsxRuntimeExports.jsx("div",{children:"Image displayed under protractor and/or ruler:"}),jsxRuntimeExports.jsxs("div",{children:["URL:"," ",jsxRuntimeExports.jsx("input",{type:"text",className:"perseus-widget-measurer-url",ref:"image-url",defaultValue:image.url,onChange:this._changeUrl}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),image.url&&jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("label",{className:"perseus-widget-left-col",children:["Pixels from top:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:0,onChange:this._changeTop,value:image.top,useArrowKeys:true})]}),jsxRuntimeExports.jsxs("label",{className:"perseus-widget-right-col",children:["Pixels from left:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:0,onChange:this._changeLeft,value:image.left,useArrowKeys:true})]})]}),jsxRuntimeExports.jsxs("div",{children:["Containing area [width, height]:"," ",jsxRuntimeExports.jsx(RangeInput$2,{onChange:this.change("box"),value:this.props.box,useArrowKeys:true})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show ruler",checked:this.props.showRuler,onChange:value=>{this.props.onChange({showRuler:value});}})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.props.onChange({showProtractor:value});}})})]}),this.props.showRuler&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:[" ","Ruler label:"," ",jsxRuntimeExports.jsxs("select",{onChange:e=>this.change("rulerLabel",e.target.value),value:this.props.rulerLabel,children:[jsxRuntimeExports.jsx("option",{value:"",children:"None"}),jsxRuntimeExports.jsx("optgroup",{label:"Metric",children:this.renderLabelChoices([["milimeters","mm"],["centimeters","cm"],["meters","m"],["kilometers","km"]])}),jsxRuntimeExports.jsx("optgroup",{label:"Imperial",children:this.renderLabelChoices([["inches","in"],["feet","ft"],["yards","yd"],["miles","mi"]])})]})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:[" ","Ruler ticks:"," ",jsxRuntimeExports.jsx("select",{onChange:e=>this.change("rulerTicks",+e.target.value),value:this.props.rulerTicks,children:[1,2,4,8,10,16].map(function(n){return jsxRuntimeExports.jsx("option",{value:n,children:n},n)})})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Ruler pixels per unit:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:40,onChange:this.change("rulerPixels"),value:this.props.rulerPixels,useArrowKeys:true})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Ruler length in units:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:10,onChange:this.change("rulerLength"),value:this.props.rulerLength,useArrowKeys:true})]})})]})]})}constructor(...args){super(...args),this.className="perseus-widget-measurer",this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this._changeUrl=e=>{this._changeImage("url",e.target.value);},this._changeTop=newTop=>{this._changeImage("top",newTop);},this._changeLeft=newLeft=>{this._changeImage("left",newLeft);},this._changeImage=(subProp,newValue)=>{const image=_.clone(this.props.image);image[subProp]=newValue;this.change("image",image);},this.renderLabelChoices=choices=>{return choices.map(function(nameAndValue){const[name,value]=nameAndValue;return jsxRuntimeExports.jsx("option",{value:value,children:name},value)})},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}MeasurerEditor.widgetName="measurer";MeasurerEditor.defaultProps=measurerLogic.defaultWidgetOptions;
1837
+ const{NumberInput: NumberInput$4,RangeInput: RangeInput$2}=components;const defaultImage={url:null,top:0,left:0};class MeasurerEditor extends React.Component{render(){const image=_.extend({},defaultImage,this.props.image);return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-measurer",children:[jsxRuntimeExports.jsx("div",{children:"Image displayed under protractor and/or ruler:"}),jsxRuntimeExports.jsxs("div",{children:["URL:"," ",jsxRuntimeExports.jsx("input",{type:"text",className:"perseus-widget-measurer-url",ref:"image-url",defaultValue:image.url,onChange:this._changeUrl}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),image.url&&jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("label",{className:"perseus-widget-left-col",children:["Pixels from top:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:0,onChange:this._changeTop,value:image.top,useArrowKeys:true})]}),jsxRuntimeExports.jsxs("label",{className:"perseus-widget-right-col",children:["Pixels from left:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:0,onChange:this._changeLeft,value:image.left,useArrowKeys:true})]})]}),jsxRuntimeExports.jsxs("div",{children:["Containing area [width, height]:"," ",jsxRuntimeExports.jsx(RangeInput$2,{onChange:this.change("box"),value:this.props.box,useArrowKeys:true})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show ruler",checked:this.props.showRuler,onChange:value=>{this.props.onChange({showRuler:value});}})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.props.onChange({showProtractor:value});}})})]}),this.props.showRuler&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:[" ","Ruler label:"," ",jsxRuntimeExports.jsxs("select",{onChange:e=>this.change("rulerLabel",e.target.value),value:this.props.rulerLabel,children:[jsxRuntimeExports.jsx("option",{value:"",children:"None"}),jsxRuntimeExports.jsx("optgroup",{label:"Metric",children:this.renderLabelChoices([["milimeters","mm"],["centimeters","cm"],["meters","m"],["kilometers","km"]])}),jsxRuntimeExports.jsx("optgroup",{label:"Imperial",children:this.renderLabelChoices([["inches","in"],["feet","ft"],["yards","yd"],["miles","mi"]])})]})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:[" ","Ruler ticks:"," ",jsxRuntimeExports.jsx("select",{onChange:e=>this.change("rulerTicks",+e.target.value),value:this.props.rulerTicks,children:[1,2,4,8,10,16].map(function(n){return jsxRuntimeExports.jsx("option",{value:n,children:n},n)})})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Ruler pixels per unit:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:40,onChange:this.change("rulerPixels"),value:this.props.rulerPixels,useArrowKeys:true})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Ruler length in units:"," ",jsxRuntimeExports.jsx(NumberInput$4,{placeholder:10,onChange:this.change("rulerLength"),value:this.props.rulerLength,useArrowKeys:true})]})})]})]})}constructor(...args){super(...args),this.className="perseus-widget-measurer",this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)},this._changeUrl=e=>{this._changeImage("url",e.target.value);},this._changeTop=newTop=>{this._changeImage("top",newTop);},this._changeLeft=newLeft=>{this._changeImage("left",newLeft);},this._changeImage=(subProp,newValue)=>{const image=_.clone(this.props.image);image[subProp]=newValue;this.change("image",image);},this.renderLabelChoices=choices=>{return choices.map(function(nameAndValue){const[name,value]=nameAndValue;return jsxRuntimeExports.jsx("option",{value:value,children:name},value)})},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}MeasurerEditor.defaultProps=measurerLogic.defaultWidgetOptions;
1843
1838
 
1844
- const{ButtonGroup,NumberInput: NumberInput$3,RangeInput: RangeInput$1}=components;const bound=(x,gt,lt)=>Math.min(Math.max(x,gt),lt);const EN_DASH="–";class NumberLineEditor extends React.Component{render(){const range=this.props.range;const labelRange=this.props.labelRange;const divisionRange=this.props.divisionRange;range[0]=+range[0];range[1]=+range[1];const width=range[1]-range[0];const numDivisions=this.props.numDivisions;const snapDivisions=this.props.snapDivisions;const tickStep=this.props.tickStep;const isTickCtrl=this.props.isTickCtrl;let step;if(!isTickCtrl){step=tickStep?tickStep/snapDivisions:width/numDivisions/snapDivisions;}else {step=null;}const labelStyleEditorButtons=[{value:"decimal",content:"0.75",title:"Decimals"},{value:"improper",content:"⁷⁄₄",title:"Improper fractions"},{value:"mixed",content:"1¾",title:"Mixed numbers"},{value:"non-reduced",content:"⁸⁄₄",title:"Non-reduced"}];return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-number-line-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Correct x"," ",jsxRuntimeExports.jsxs("select",{value:this.props.correctRel,onChange:this.onChangeRelation,"aria-label":"Select relationship",children:[jsxRuntimeExports.jsx("option",{value:"eq","aria-label":"Equal",children:"="}),jsxRuntimeExports.jsx("option",{value:"lt","aria-label":"Less than",children:"<"}),jsxRuntimeExports.jsx("option",{value:"gt","aria-label":"Greater than",children:">"}),jsxRuntimeExports.jsx("option",{value:"le","aria-label":"Less than or equal",children:"≤"}),jsxRuntimeExports.jsx("option",{value:"ge","aria-label":"Greater than or equal",children:"≥"})]})," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.correctX,format:this.props.labelStyle,onChange:this.onNumChange.bind(this,"correctX"),checkValidity:val=>val>=range[0]&&val<=range[1]&&(!step||number.isInteger((val-range[0])/step)),placeholder:"answer",size:"normal",useArrowKeys:true}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"This is the correct answer. The answer is validated (as right or wrong) by using only the end position of the point and the relation (=, <, >, ≤, ≥)."})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[this.props.static?jsxRuntimeExports.jsx("label",{children:"Range:"}):jsxRuntimeExports.jsxs("label",{children:["Position:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.initialX,format:this.props.labelStyle,onChange:this.onNumChange.bind(this,"initialX"),placeholder:range[0],checkValidity:val=>{return val>=range[0]&&val<=range[1]},useArrowKeys:true})," ∈ "]}),jsxRuntimeExports.jsx(RangeInput$1,{value:range,onChange:this.onRangeChange,format:this.props.labelStyle,useArrowKeys:true}),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsxs("p",{children:["This controls the initial position of the point along the number line and the",jsxRuntimeExports.jsx("strong",{children:"range"}),", the position of the endpoints of the number line. Setting the range constrains the position of the answer and the labels."]}),jsxRuntimeExports.jsx("p",{children:"In static mode, the initial position of the point is determined by Correct x instead of position."})]})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:["Labels:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:labelRange[0],placeholder:range[0],format:this.props.labelStyle,checkValidity:val=>val>=range[0]&&val<=range[1],onChange:this.onLabelRangeChange.bind(this,0),useArrowKeys:true}),jsxRuntimeExports.jsx("span",{children:" & "}),jsxRuntimeExports.jsx(NumberInput$3,{value:labelRange[1],placeholder:range[1],format:this.props.labelStyle,checkValidity:val=>val>=range[0]&&val<=range[1],onChange:this.onLabelRangeChange.bind(this,1),useArrowKeys:true}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This controls the position of the left / right labels. By default, the labels are set by the range ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"})," Ensure that the labels line up with the tick marks, or it may be confusing for users."]})})]})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Style:"," ",jsxRuntimeExports.jsx(ButtonGroup,{allowEmpty:false,value:this.props.labelStyle,buttons:labelStyleEditorButtons,onChange:this.onLabelStyleChange}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"This controls the styling of the labels for the two main labels as well as all the tick mark labels, if applicable. Your choices are decimal, improper fractions, mixed fractions, and non-reduced fractions."})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[!this.props.static&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tick controller",checked:!!this.props.isTickCtrl,onChange:value=>{this.props.onChange({isTickCtrl:value});}})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show label ticks",checked:this.props.labelTicks,onChange:value=>{this.props.onChange({labelTicks:value});}})})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:!this.props.static&&jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tooltips",checked:this.props.showTooltips,onChange:value=>{this.props.onChange({showTooltips:value});}})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[isTickCtrl&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:["Start num divisions at"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.numDivisions||null,format:"decimal",onChange:this.onNumDivisionsChange,checkValidity:val=>{return val>=divisionRange[0]&&val<=divisionRange[1]},placeholder:width/this.props.tickStep,useArrowKeys:true})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This controls the number (and position) of the tick marks. The number of divisions is constrained to"," "+divisionRange[0]+EN_DASH+divisionRange[1],".",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"})," The user will be able to specify the number of divisions in a number input."]})})]}),!isTickCtrl&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:["Num divisions:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.numDivisions||null,format:"decimal",onChange:this.onNumDivisionsChange,checkValidity:val=>{return val>=divisionRange[0]&&val<=divisionRange[1]},placeholder:width/this.props.tickStep,useArrowKeys:true})]})," ",jsxRuntimeExports.jsxs("label",{children:["or tick step:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.tickStep||null,format:this.props.labelStyle,onChange:this.onTickStepChange,checkValidity:val=>{return val>0&&val<=width},placeholder:width/this.props.numDivisions,useArrowKeys:true})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This controls the number (and position) of the tick marks; you can either set the number of divisions (2 divisions would split the entire range in two halves), or the tick step (the distance between ticks) and the other value will be updated accordingly."," ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"})," There is no check to see if labels coordinate with the tick marks, which may be confusing for users if the blue labels and black ticks are off-step."]})})]})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("label",{children:["Snap increments per tick:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:snapDivisions,checkValidity:val=>val>0,format:this.props.labelStyle,onChange:this.onNumChange.bind(this,"snapDivisions"),useArrowKeys:true})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This determines the number of different places the point will snap between two adjacent tick marks."," ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"}),"Ensure the required number of snap increments is provided to answer the question."]})})]})]})}constructor(...args){super(...args),this.onRangeChange=range=>{this.props.onChange({range:range});},this.onLabelRangeChange=(i,num)=>{let labelRange=this.props.labelRange.slice();const otherNum=labelRange[1-i];if(num==null||otherNum==null){labelRange[i]=num;}else {labelRange=[Math.min(num,otherNum),Math.max(num,otherNum)];}this.props.onChange({labelRange:labelRange});},this.onDivisionRangeChange=divisionRange=>{let numDivisions=this.props.numDivisions;numDivisions=bound(numDivisions,divisionRange[0],divisionRange[1]);this.props.onChange({divisionRange:divisionRange,numDivisions:numDivisions});},this.onNumChange=(key,value)=>{const opts={};opts[key]=value;this.props.onChange(opts);},this.onNumDivisionsChange=numDivisions=>{const divRange=this.props.divisionRange.slice();numDivisions=_.isFinite(numDivisions)?Math.round(numDivisions):0;numDivisions=numDivisions<0?numDivisions*-1:numDivisions;if(numDivisions){numDivisions=Math.min(divRange[1],Math.max(divRange[0],numDivisions));this.props.onChange({tickStep:null,divisionRange:divRange,numDivisions:numDivisions});}},this.onTickStepChange=tickStep=>{this.props.onChange({numDivisions:null,tickStep:tickStep});},this.onChangeRelation=e=>{const value=e.target.value;this.props.onChange({correctRel:value,isInequality:value!=="eq"});},this.onLabelStyleChange=labelStyle=>{this.props.onChange({labelStyle:labelStyle});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}NumberLineEditor.widgetName="number-line";NumberLineEditor.defaultProps=numberLineLogic.defaultWidgetOptions;
1839
+ const{ButtonGroup,NumberInput: NumberInput$3,RangeInput: RangeInput$1}=components;const bound=(x,gt,lt)=>Math.min(Math.max(x,gt),lt);const EN_DASH="–";class NumberLineEditor extends React.Component{render(){const range=this.props.range;const labelRange=this.props.labelRange;const divisionRange=this.props.divisionRange;range[0]=+range[0];range[1]=+range[1];const width=range[1]-range[0];const numDivisions=this.props.numDivisions;const snapDivisions=this.props.snapDivisions;const tickStep=this.props.tickStep;const isTickCtrl=this.props.isTickCtrl;let step;if(!isTickCtrl){step=tickStep?tickStep/snapDivisions:width/numDivisions/snapDivisions;}else {step=null;}const labelStyleEditorButtons=[{value:"decimal",content:"0.75",title:"Decimals"},{value:"improper",content:"⁷⁄₄",title:"Improper fractions"},{value:"mixed",content:"1¾",title:"Mixed numbers"},{value:"non-reduced",content:"⁸⁄₄",title:"Non-reduced"}];return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-number-line-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Correct x"," ",jsxRuntimeExports.jsxs("select",{value:this.props.correctRel,onChange:this.onChangeRelation,"aria-label":"Select relationship",children:[jsxRuntimeExports.jsx("option",{value:"eq","aria-label":"Equal",children:"="}),jsxRuntimeExports.jsx("option",{value:"lt","aria-label":"Less than",children:"<"}),jsxRuntimeExports.jsx("option",{value:"gt","aria-label":"Greater than",children:">"}),jsxRuntimeExports.jsx("option",{value:"le","aria-label":"Less than or equal",children:"≤"}),jsxRuntimeExports.jsx("option",{value:"ge","aria-label":"Greater than or equal",children:"≥"})]})," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.correctX,format:this.props.labelStyle,onChange:this.onNumChange.bind(this,"correctX"),checkValidity:val=>val>=range[0]&&val<=range[1]&&(!step||number.isInteger((val-range[0])/step)),placeholder:"answer",size:"normal",useArrowKeys:true}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"This is the correct answer. The answer is validated (as right or wrong) by using only the end position of the point and the relation (=, <, >, ≤, ≥)."})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[this.props.static?jsxRuntimeExports.jsx("label",{children:"Range:"}):jsxRuntimeExports.jsxs("label",{children:["Position:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.initialX,format:this.props.labelStyle,onChange:this.onNumChange.bind(this,"initialX"),placeholder:range[0],checkValidity:val=>{return val>=range[0]&&val<=range[1]},useArrowKeys:true})," ∈ "]}),jsxRuntimeExports.jsx(RangeInput$1,{value:range,onChange:this.onRangeChange,format:this.props.labelStyle,useArrowKeys:true}),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsxs("p",{children:["This controls the initial position of the point along the number line and the",jsxRuntimeExports.jsx("strong",{children:"range"}),", the position of the endpoints of the number line. Setting the range constrains the position of the answer and the labels."]}),jsxRuntimeExports.jsx("p",{children:"In static mode, the initial position of the point is determined by Correct x instead of position."})]})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:["Labels:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:labelRange[0],placeholder:range[0],format:this.props.labelStyle,checkValidity:val=>val>=range[0]&&val<=range[1],onChange:this.onLabelRangeChange.bind(this,0),useArrowKeys:true}),jsxRuntimeExports.jsx("span",{children:" & "}),jsxRuntimeExports.jsx(NumberInput$3,{value:labelRange[1],placeholder:range[1],format:this.props.labelStyle,checkValidity:val=>val>=range[0]&&val<=range[1],onChange:this.onLabelRangeChange.bind(this,1),useArrowKeys:true}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This controls the position of the left / right labels. By default, the labels are set by the range ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"})," Ensure that the labels line up with the tick marks, or it may be confusing for users."]})})]})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Style:"," ",jsxRuntimeExports.jsx(ButtonGroup,{allowEmpty:false,value:this.props.labelStyle,buttons:labelStyleEditorButtons,onChange:this.onLabelStyleChange}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"This controls the styling of the labels for the two main labels as well as all the tick mark labels, if applicable. Your choices are decimal, improper fractions, mixed fractions, and non-reduced fractions."})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[!this.props.static&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tick controller",checked:!!this.props.isTickCtrl,onChange:value=>{this.props.onChange({isTickCtrl:value});}})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show label ticks",checked:this.props.labelTicks,onChange:value=>{this.props.onChange({labelTicks:value});}})})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:!this.props.static&&jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tooltips",checked:this.props.showTooltips,onChange:value=>{this.props.onChange({showTooltips:value});}})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[isTickCtrl&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:["Start num divisions at"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.numDivisions||null,format:"decimal",onChange:this.onNumDivisionsChange,checkValidity:val=>{return val>=divisionRange[0]&&val<=divisionRange[1]},placeholder:width/this.props.tickStep,useArrowKeys:true})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This controls the number (and position) of the tick marks. The number of divisions is constrained to"," "+divisionRange[0]+EN_DASH+divisionRange[1],".",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"})," The user will be able to specify the number of divisions in a number input."]})})]}),!isTickCtrl&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:["Num divisions:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.numDivisions||null,format:"decimal",onChange:this.onNumDivisionsChange,checkValidity:val=>{return val>=divisionRange[0]&&val<=divisionRange[1]},placeholder:width/this.props.tickStep,useArrowKeys:true})]})," ",jsxRuntimeExports.jsxs("label",{children:["or tick step:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:this.props.tickStep||null,format:this.props.labelStyle,onChange:this.onTickStepChange,checkValidity:val=>{return val>0&&val<=width},placeholder:width/this.props.numDivisions,useArrowKeys:true})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This controls the number (and position) of the tick marks; you can either set the number of divisions (2 divisions would split the entire range in two halves), or the tick step (the distance between ticks) and the other value will be updated accordingly."," ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"})," There is no check to see if labels coordinate with the tick marks, which may be confusing for users if the blue labels and black ticks are off-step."]})})]})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsxs("label",{children:["Snap increments per tick:"," ",jsxRuntimeExports.jsx(NumberInput$3,{value:snapDivisions,checkValidity:val=>val>0,format:this.props.labelStyle,onChange:this.onNumChange.bind(this,"snapDivisions"),useArrowKeys:true})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsxs("p",{children:["This determines the number of different places the point will snap between two adjacent tick marks."," ",jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("strong",{children:"Note:"}),"Ensure the required number of snap increments is provided to answer the question."]})})]})]})}constructor(...args){super(...args),this.onRangeChange=range=>{this.props.onChange({range:range});},this.onLabelRangeChange=(i,num)=>{let labelRange=this.props.labelRange.slice();const otherNum=labelRange[1-i];if(num==null||otherNum==null){labelRange[i]=num;}else {labelRange=[Math.min(num,otherNum),Math.max(num,otherNum)];}this.props.onChange({labelRange:labelRange});},this.onDivisionRangeChange=divisionRange=>{let numDivisions=this.props.numDivisions;numDivisions=bound(numDivisions,divisionRange[0],divisionRange[1]);this.props.onChange({divisionRange:divisionRange,numDivisions:numDivisions});},this.onNumChange=(key,value)=>{const opts={};opts[key]=value;this.props.onChange(opts);},this.onNumDivisionsChange=numDivisions=>{const divRange=this.props.divisionRange.slice();numDivisions=_.isFinite(numDivisions)?Math.round(numDivisions):0;numDivisions=numDivisions<0?numDivisions*-1:numDivisions;if(numDivisions){numDivisions=Math.min(divRange[1],Math.max(divRange[0],numDivisions));this.props.onChange({tickStep:null,divisionRange:divRange,numDivisions:numDivisions});}},this.onTickStepChange=tickStep=>{this.props.onChange({numDivisions:null,tickStep:tickStep});},this.onChangeRelation=e=>{const value=e.target.value;this.props.onChange({correctRel:value,isInequality:value!=="eq"});},this.onLabelStyleChange=labelStyle=>{this.props.onChange({labelStyle:labelStyle});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}NumberLineEditor.defaultProps=numberLineLogic.defaultWidgetOptions;
1845
1840
 
1846
- const NORMAL="normal";const AUTO="auto";const HORIZONTAL="horizontal";const VERTICAL="vertical";class OrdererEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Place the cards in the correct order. The same card can be used more than once in the answer but will only be displayed once at the top of a stack of identical cards."})})]}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.correctOptions.map(option=>option.content),onChange:options=>{this.onOptionsChange("correctOptions",options);},layout:this.props.layout}),jsxRuntimeExports.jsxs("div",{children:[" ","Other cards:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Create cards that are not part of the answer."})})]}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.otherOptions.map(option=>option.content),onChange:options=>{this.onOptionsChange("otherOptions",options);},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,{children:jsxRuntimeExports.jsx("p",{children:"Use the horizontal layout for short text and small images. The vertical layout is best for longer text (e.g. proofs)."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Height:"," ",jsxRuntimeExports.jsxs("select",{value:this.props.height,onChange:this.onHeightChange,children:[jsxRuntimeExports.jsx("option",{value:NORMAL,children:"Normal"}),jsxRuntimeExports.jsx("option",{value:AUTO,children:"Automatic"})]})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Use "Normal" for text, "Automatic" for images.'})})]})]})}constructor(...args){super(...args),this.onOptionsChange=(whichOptions,options)=>{const changedCards=options.map(toCard);const correctOptions=whichOptions==="correctOptions"?changedCards:this.props.correctOptions;const otherOptions=whichOptions==="otherOptions"?changedCards:this.props.otherOptions;this.props.onChange({[whichOptions]:changedCards,options:mergeCards(correctOptions,otherOptions)});},this.onLayoutChange=e=>{const layout=e.target.value;switch(layout){case HORIZONTAL:case VERTICAL:this.props.onChange({layout});break;default:throw new Error(`${layout} is not an available layout option`)}},this.onHeightChange=e=>{const height=e.target.value;switch(height){case NORMAL:case AUTO:this.props.onChange({height});break;default:throw new Error(`${height} is not an available height option`)}},this.serialize=()=>{return {options:mergeCards(this.props.correctOptions,this.props.otherOptions),correctOptions:this.props.correctOptions,otherOptions:this.props.otherOptions,height:this.props.height,layout:this.props.layout}};}}OrdererEditor.widgetName="orderer";OrdererEditor.defaultProps=ordererLogic.defaultWidgetOptions;
1841
+ const NORMAL="normal";const AUTO="auto";const HORIZONTAL="horizontal";const VERTICAL="vertical";class OrdererEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Place the cards in the correct order. The same card can be used more than once in the answer but will only be displayed once at the top of a stack of identical cards."})})]}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.correctOptions.map(option=>option.content),onChange:options=>{this.onOptionsChange("correctOptions",options);},layout:this.props.layout}),jsxRuntimeExports.jsxs("div",{children:[" ","Other cards:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Create cards that are not part of the answer."})})]}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.otherOptions.map(option=>option.content),onChange:options=>{this.onOptionsChange("otherOptions",options);},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,{children:jsxRuntimeExports.jsx("p",{children:"Use the horizontal layout for short text and small images. The vertical layout is best for longer text (e.g. proofs)."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Height:"," ",jsxRuntimeExports.jsxs("select",{value:this.props.height,onChange:this.onHeightChange,children:[jsxRuntimeExports.jsx("option",{value:NORMAL,children:"Normal"}),jsxRuntimeExports.jsx("option",{value:AUTO,children:"Automatic"})]})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Use "Normal" for text, "Automatic" for images.'})})]})]})}constructor(...args){super(...args),this.onOptionsChange=(whichOptions,options)=>{const changedCards=options.map(toCard);const correctOptions=whichOptions==="correctOptions"?changedCards:this.props.correctOptions;const otherOptions=whichOptions==="otherOptions"?changedCards:this.props.otherOptions;this.props.onChange({[whichOptions]:changedCards,options:mergeCards(correctOptions,otherOptions)});},this.onLayoutChange=e=>{const layout=e.target.value;switch(layout){case HORIZONTAL:case VERTICAL:this.props.onChange({layout});break;default:throw new Error(`${layout} is not an available layout option`)}},this.onHeightChange=e=>{const height=e.target.value;switch(height){case NORMAL:case AUTO:this.props.onChange({height});break;default:throw new Error(`${height} is not an available height option`)}},this.serialize=()=>{return {options:mergeCards(this.props.correctOptions,this.props.otherOptions),correctOptions:this.props.correctOptions,otherOptions:this.props.otherOptions,height:this.props.height,layout:this.props.layout}};}}OrdererEditor.defaultProps=ordererLogic.defaultWidgetOptions;
1847
1842
 
1848
- class PhetSimulationEditor extends React.Component{serialize(){return {url:this.props.url,description:this.props.description}}render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(LabeledTextField,{label:"URL",value:this.props.url,onChange:url=>this.props.onChange({url}),style:{marginBlockEnd:spacing.large_24}}),jsxRuntimeExports.jsx(LabeledTextField,{label:"Description",value:this.props.description,onChange:description=>this.props.onChange({description})})]})}constructor(...args){super(...args),this.getSaveWarnings=()=>{if(makeSafeUrl(this.props.url,"en","https://phet.colorado.edu")===null){return ["Please enter a URL from the PhET domain."]}return []};}}PhetSimulationEditor.defaultProps=phetSimulationLogic.defaultWidgetOptions;PhetSimulationEditor.widgetName="phet-simulation";
1843
+ class PhetSimulationEditor extends React.Component{serialize(){return {url:this.props.url,description:this.props.description}}render(){return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(LabeledTextField,{label:"URL",value:this.props.url,onChange:url=>this.props.onChange({url}),style:{marginBlockEnd:spacing.large_24}}),jsxRuntimeExports.jsx(LabeledTextField,{label:"Description",value:this.props.description,onChange:description=>this.props.onChange({description})})]})}constructor(...args){super(...args),this.getSaveWarnings=()=>{if(makeSafeUrl(this.props.url,"en","https://phet.colorado.edu")===null){return ["Please enter a URL from the PhET domain."]}return []};}}PhetSimulationEditor.defaultProps=phetSimulationLogic.defaultWidgetOptions;
1849
1844
 
1850
- const{NumberInput: NumberInput$2,RangeInput}=components;const Plotter=PlotterWidget.widget;const STARTING="starting";const CORRECT="correct";const editingStates=[STARTING,CORRECT];function padArray(array,n,value){const copy=_.clone(array);copy.length=n;for(let i=array.length;i<n;i++){copy[i]=value;}return copy}const editorDefaults={scaleY:1,maxY:10,snapsPerLine:2};const formatNumber=num=>"$"+number.round(num,2)+"$";class PlotterEditor extends React.Component{UNSAFE_componentWillMount(){this.fetchPic(this.props.picUrl);}UNSAFE_componentWillReceiveProps(nextProps){this.fetchPic(nextProps.picUrl);if(nextProps.static){this.setState({editing:"starting"});}}render(){const setFromScale=["line","histogram","dotplot"].includes(this.props.type);const canChangeSnaps=!["pic","dotplot"].includes(this.props.type);const plotterProps={options:{type:this.props.type,labels:this.props.labels,categories:this.props.categories,scaleY:this.props.scaleY,maxY:this.props.maxY,snapsPerLine:this.props.snapsPerLine,picUrl:this.props.picUrl,picSize:this.props.picSize,picBoxHeight:this.props.picBoxHeight,plotDimensions:this.props.plotDimensions,labelInterval:this.props.labelInterval,starting:this.props[this.state.editing]},apiOptions:this.props.apiOptions,static:this.props.static,trackInteraction:()=>{},userInput:this.props.correct,handleUserInput:userInput=>{this.props.onChange({correct:userInput});}};return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-plotter-editor",children:[jsxRuntimeExports.jsxs("div",{children:["Chart type:"," ",plotterPlotTypes.map(type=>{return jsxRuntimeExports.jsxs("label",{children:[jsxRuntimeExports.jsx("input",{type:"radio",name:"chart-type",checked:this.props.type===type,onChange:_.partial(this.changeType,type)}),type]},type)},this)]}),jsxRuntimeExports.jsxs("div",{children:["Labels:"," ",["x","y"].map((axis,i)=>{return jsxRuntimeExports.jsxs("label",{children:[axis+":",jsxRuntimeExports.jsx("input",{type:"text",onChange:_.partial(this.changeLabel,i),defaultValue:this.props.labels[i]})]},axis)},this)]}),setFromScale&&jsxRuntimeExports.jsxs("div",{className:"set-from-scale-box",children:[jsxRuntimeExports.jsx("span",{className:"categories-title",children:"Set Categories From Scale"}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Tick Step:"," ",jsxRuntimeExports.jsx(NumberInput$2,{placeholder:1,useArrowKeys:true,value:this.state.tickStep,onChange:this.handleChangeTickStep})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"The difference between adjacent ticks."})})]}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Range:"," ",jsxRuntimeExports.jsx(RangeInput,{placeholder:[0,10],useArrowKeys:true,value:[this.state.minX,this.state.maxX],onChange:this.handleChangeRange})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("button",{onClick:this.setCategoriesFromScale,children:["Set Categories"," "]})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Label Interval:"," ",jsxRuntimeExports.jsx(NumberInput$2,{useArrowKeys:true,value:this.props.labelInterval,onChange:this.changeLabelInterval})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Which ticks to display the labels for. For instance, setting this to "4" will only show every 4th label (plus the last one)'})})]}),this.props.type==="pic"&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Picture:"," ",jsxRuntimeExports.jsx(BlurInput,{className:"pic-url",value:this.props.picUrl??"",onChange:this.changePicUrl}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Use the default picture of Earth, or insert the URL for a different picture using the "Add image" function.'})})]}),this.state.pic&&this.state.pic.width!==this.state.pic.height&&jsxRuntimeExports.jsxs("p",{className:"warning",children:[jsxRuntimeExports.jsx("b",{children:"Warning"}),": You are using a picture which is not square. This means the image will get distorted. You should probably crop it to be square."]})]}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Categories:"," ",jsxRuntimeExports.jsx(TextListEditor,{ref:"categories",layout:"horizontal",options:this.props.categories,onChange:this.changeCategories})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Scale (y):"," ",jsxRuntimeExports.jsx("input",{type:"text",onChange:this.changeScale,defaultValue:this.props.scaleY})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Max y:"," ",jsxRuntimeExports.jsx("input",{type:"text",ref:"maxY",onChange:this.changeMax,defaultValue:this.props.maxY})]})}),canChangeSnaps&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Snaps per line:"," ",jsxRuntimeExports.jsx("input",{type:"text",onChange:this.changeSnaps,defaultValue:this.props.snapsPerLine})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Creates the specified number of divisions between the horizontal lines. Fewer snaps between lines makes the graph easier for the student to create correctly."})})]}),jsxRuntimeExports.jsxs("div",{children:["Editing values:"," ",editingStates.map(editing=>jsxRuntimeExports.jsxs("label",{children:[jsxRuntimeExports.jsx("input",{type:"radio",disabled:editing===CORRECT&&this.props.static,checked:this.props.static?editing===STARTING:this.state.editing===editing,onChange:e=>this.changeEditing(editing)}),editing]},editing)),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsx("p",{children:"Use this toggle to switch between editing the correct answer (what the student will be graded on) and the starting values (what the student will see plotted when they start the problem). Note: These cannot be the same."}),jsxRuntimeExports.jsx("p",{children:"In static mode, the starting values are rendered out to the displayed widget."})]})]}),jsxRuntimeExports.jsx(Plotter,{...plotterProps})]})}constructor(...args){super(...args),this.state={editing:this.props.static?STARTING:CORRECT,pic:null,loadedUrl:null,minX:null,maxX:null,tickStep:null},this.fetchPic=url=>{if(url==null){if(this.state.pic!==null){this.setState({pic:null,loadedUrl:null});}return}if(this.state.loadedUrl!==url){const pic=new Image;pic.src=url;pic.onload=()=>{this.setState({pic:pic,loadedUrl:url});};}},this.handleChangeTickStep=value=>{this.setState({tickStep:value});},this.handleChangeRange=newValue=>{this.setState({minX:newValue[0],maxX:newValue[1]});},this.changeLabelInterval=value=>{this.props.onChange({labelInterval:value});},this.changeType=type=>{let categories;if(type==="histogram"){categories=[formatNumber(0)].concat(this.props.categories);this.props.onChange({type:type,categories:categories});}else if(this.props.type==="histogram"){categories=this.props.categories.slice(1);this.props.onChange({type:type,categories:categories});}else {this.props.onChange({type:type});}if(categories){const node=ReactDOM.findDOMNode(this.refs.categories);node.value=categories.join(", ");}},this.changeLabel=(i,e)=>{const labels=_.clone(this.props.labels);labels[i]=e.target.value;this.props.onChange({labels:labels});},this.changePicUrl=value=>{const url=Util.getRealImageUrl(value);this.props.onChange({picUrl:url});},this.changeCategories=categories=>{let n=categories.length;if(this.props.type==="histogram"){n--;}const value=this.props.scaleY;this.props.onChange({categories:categories,correct:padArray(this.props.correct,n,value),starting:padArray(this.props.starting,n,value)});},this.changeScale=e=>{const oldScale=this.props.scaleY;const newScale=+e.target.value||editorDefaults.scaleY;const scale=function(value){return value*newScale/oldScale};const maxY=scale(this.props.maxY);this.props.onChange({scaleY:newScale,maxY:maxY,correct:this.props.correct.map(scale),starting:this.props.starting.map(scale)});ReactDOM.findDOMNode(this.refs.maxY).value=maxY;},this.changeMax=e=>{this.props.onChange({maxY:+e.target.value||editorDefaults.maxY});},this.changeSnaps=e=>{this.props.onChange({snapsPerLine:+e.target.value||editorDefaults.snapsPerLine});},this.changeEditing=editing=>{this.setState({editing:editing});},this.setCategoriesFromScale=()=>{const scale=this.state.tickStep||1;const min=this.state.minX||0;const max=this.state.maxX||0;const length=Math.floor((max-min)/scale)*scale;let categories;if(this.props.type==="histogram"||this.props.type==="dotplot"){categories=_.range(0,length+scale,scale);}else {categories=_.range(scale,length+scale,scale);}categories=categories.map(num=>num+min);categories=categories.map(formatNumber);this.changeCategories(categories);const node=ReactDOM.findDOMNode(this.refs.categories);node.value=categories.join(", ");},this.serialize=()=>{const json=_.pick(this.props,"correct","starting","type","labels","categories","scaleY","maxY","snapsPerLine","labelInterval");if(this.props.type==="pic"){json.picUrl=this.props.picUrl;}return json};}}PlotterEditor.widgetName="plotter";PlotterEditor.defaultProps=plotterLogic.defaultWidgetOptions;
1845
+ const{NumberInput: NumberInput$2,RangeInput}=components;const Plotter=PlotterWidget.widget;const STARTING="starting";const CORRECT="correct";const editingStates=[STARTING,CORRECT];function padArray(array,n,value){const copy=_.clone(array);copy.length=n;for(let i=array.length;i<n;i++){copy[i]=value;}return copy}const editorDefaults={scaleY:1,maxY:10,snapsPerLine:2};const formatNumber=num=>"$"+number.round(num,2)+"$";class PlotterEditor extends React.Component{UNSAFE_componentWillMount(){this.fetchPic(this.props.picUrl);}UNSAFE_componentWillReceiveProps(nextProps){this.fetchPic(nextProps.picUrl);if(nextProps.static){this.setState({editing:"starting"});}}render(){const setFromScale=["line","histogram","dotplot"].includes(this.props.type);const canChangeSnaps=!["pic","dotplot"].includes(this.props.type);const plotterProps={options:{type:this.props.type,labels:this.props.labels,categories:this.props.categories,scaleY:this.props.scaleY,maxY:this.props.maxY,snapsPerLine:this.props.snapsPerLine,picUrl:this.props.picUrl,picSize:this.props.picSize,picBoxHeight:this.props.picBoxHeight,plotDimensions:this.props.plotDimensions,labelInterval:this.props.labelInterval,starting:this.props[this.state.editing]},apiOptions:this.props.apiOptions,static:this.props.static,trackInteraction:()=>{},userInput:this.props.correct,handleUserInput:userInput=>{this.props.onChange({correct:userInput});}};return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-plotter-editor",children:[jsxRuntimeExports.jsxs("div",{children:["Chart type:"," ",plotterPlotTypes.map(type=>{return jsxRuntimeExports.jsxs("label",{children:[jsxRuntimeExports.jsx("input",{type:"radio",name:"chart-type",checked:this.props.type===type,onChange:_.partial(this.changeType,type)}),type]},type)},this)]}),jsxRuntimeExports.jsxs("div",{children:["Labels:"," ",["x","y"].map((axis,i)=>{return jsxRuntimeExports.jsxs("label",{children:[axis+":",jsxRuntimeExports.jsx("input",{type:"text",onChange:_.partial(this.changeLabel,i),defaultValue:this.props.labels[i]})]},axis)},this)]}),setFromScale&&jsxRuntimeExports.jsxs("div",{className:"set-from-scale-box",children:[jsxRuntimeExports.jsx("span",{className:"categories-title",children:"Set Categories From Scale"}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Tick Step:"," ",jsxRuntimeExports.jsx(NumberInput$2,{placeholder:1,useArrowKeys:true,value:this.state.tickStep,onChange:this.handleChangeTickStep})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"The difference between adjacent ticks."})})]}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Range:"," ",jsxRuntimeExports.jsx(RangeInput,{placeholder:[0,10],useArrowKeys:true,value:[this.state.minX,this.state.maxX],onChange:this.handleChangeRange})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("button",{onClick:this.setCategoriesFromScale,children:["Set Categories"," "]})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Label Interval:"," ",jsxRuntimeExports.jsx(NumberInput$2,{useArrowKeys:true,value:this.props.labelInterval,onChange:this.changeLabelInterval})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Which ticks to display the labels for. For instance, setting this to "4" will only show every 4th label (plus the last one)'})})]}),this.props.type==="pic"&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Picture:"," ",jsxRuntimeExports.jsx(BlurInput,{className:"pic-url",value:this.props.picUrl??"",onChange:this.changePicUrl}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:'Use the default picture of Earth, or insert the URL for a different picture using the "Add image" function.'})})]}),this.state.pic&&this.state.pic.width!==this.state.pic.height&&jsxRuntimeExports.jsxs("p",{className:"warning",children:[jsxRuntimeExports.jsx("b",{children:"Warning"}),": You are using a picture which is not square. This means the image will get distorted. You should probably crop it to be square."]})]}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Categories:"," ",jsxRuntimeExports.jsx(TextListEditor,{ref:"categories",layout:"horizontal",options:this.props.categories,onChange:this.changeCategories})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Scale (y):"," ",jsxRuntimeExports.jsx("input",{type:"text",onChange:this.changeScale,defaultValue:this.props.scaleY})]})}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("label",{children:["Max y:"," ",jsxRuntimeExports.jsx("input",{type:"text",ref:"maxY",onChange:this.changeMax,defaultValue:this.props.maxY})]})}),canChangeSnaps&&jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:["Snaps per line:"," ",jsxRuntimeExports.jsx("input",{type:"text",onChange:this.changeSnaps,defaultValue:this.props.snapsPerLine})]}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Creates the specified number of divisions between the horizontal lines. Fewer snaps between lines makes the graph easier for the student to create correctly."})})]}),jsxRuntimeExports.jsxs("div",{children:["Editing values:"," ",editingStates.map(editing=>jsxRuntimeExports.jsxs("label",{children:[jsxRuntimeExports.jsx("input",{type:"radio",disabled:editing===CORRECT&&this.props.static,checked:this.props.static?editing===STARTING:this.state.editing===editing,onChange:e=>this.changeEditing(editing)}),editing]},editing)),jsxRuntimeExports.jsxs(InfoTip,{children:[jsxRuntimeExports.jsx("p",{children:"Use this toggle to switch between editing the correct answer (what the student will be graded on) and the starting values (what the student will see plotted when they start the problem). Note: These cannot be the same."}),jsxRuntimeExports.jsx("p",{children:"In static mode, the starting values are rendered out to the displayed widget."})]})]}),jsxRuntimeExports.jsx(Plotter,{...plotterProps})]})}constructor(...args){super(...args),this.state={editing:this.props.static?STARTING:CORRECT,pic:null,loadedUrl:null,minX:null,maxX:null,tickStep:null},this.fetchPic=url=>{if(url==null){if(this.state.pic!==null){this.setState({pic:null,loadedUrl:null});}return}if(this.state.loadedUrl!==url){const pic=new Image;pic.src=url;pic.onload=()=>{this.setState({pic:pic,loadedUrl:url});};}},this.handleChangeTickStep=value=>{this.setState({tickStep:value});},this.handleChangeRange=newValue=>{this.setState({minX:newValue[0],maxX:newValue[1]});},this.changeLabelInterval=value=>{this.props.onChange({labelInterval:value});},this.changeType=type=>{let categories;if(type==="histogram"){categories=[formatNumber(0)].concat(this.props.categories);this.props.onChange({type:type,categories:categories});}else if(this.props.type==="histogram"){categories=this.props.categories.slice(1);this.props.onChange({type:type,categories:categories});}else {this.props.onChange({type:type});}if(categories){const node=ReactDOM.findDOMNode(this.refs.categories);node.value=categories.join(", ");}},this.changeLabel=(i,e)=>{const labels=_.clone(this.props.labels);labels[i]=e.target.value;this.props.onChange({labels:labels});},this.changePicUrl=value=>{const url=Util.getRealImageUrl(value);this.props.onChange({picUrl:url});},this.changeCategories=categories=>{let n=categories.length;if(this.props.type==="histogram"){n--;}const value=this.props.scaleY;this.props.onChange({categories:categories,correct:padArray(this.props.correct,n,value),starting:padArray(this.props.starting,n,value)});},this.changeScale=e=>{const oldScale=this.props.scaleY;const newScale=+e.target.value||editorDefaults.scaleY;const scale=function(value){return value*newScale/oldScale};const maxY=scale(this.props.maxY);this.props.onChange({scaleY:newScale,maxY:maxY,correct:this.props.correct.map(scale),starting:this.props.starting.map(scale)});ReactDOM.findDOMNode(this.refs.maxY).value=maxY;},this.changeMax=e=>{this.props.onChange({maxY:+e.target.value||editorDefaults.maxY});},this.changeSnaps=e=>{this.props.onChange({snapsPerLine:+e.target.value||editorDefaults.snapsPerLine});},this.changeEditing=editing=>{this.setState({editing:editing});},this.setCategoriesFromScale=()=>{const scale=this.state.tickStep||1;const min=this.state.minX||0;const max=this.state.maxX||0;const length=Math.floor((max-min)/scale)*scale;let categories;if(this.props.type==="histogram"||this.props.type==="dotplot"){categories=_.range(0,length+scale,scale);}else {categories=_.range(scale,length+scale,scale);}categories=categories.map(num=>num+min);categories=categories.map(formatNumber);this.changeCategories(categories);const node=ReactDOM.findDOMNode(this.refs.categories);node.value=categories.join(", ");},this.serialize=()=>{const json=_.pick(this.props,"correct","starting","type","labels","categories","scaleY","maxY","snapsPerLine","labelInterval");if(this.props.type==="pic"){json.picUrl=this.props.picUrl;}return json};}}PlotterEditor.defaultProps=plotterLogic.defaultWidgetOptions;
1851
1846
 
1852
- 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 deprecatedChangeableChange.apply(this,args)},this.getSaveWarnings=()=>{return validateOptions(this.props.height,this.props.programID)};}}PythonProgramEditor.widgetName="python-program";PythonProgramEditor.defaultProps=pythonProgramLogic.defaultWidgetOptions;
1847
+ 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 deprecatedChangeableChange.apply(this,args)},this.getSaveWarnings=()=>{return validateOptions(this.props.height,this.props.programID)};}}PythonProgramEditor.defaultProps=pythonProgramLogic.defaultWidgetOptions;
1853
1848
 
1854
1849
  var styles$2 = {"tile":"perseus_H66MpddK","statusRow":"perseus_WkPB-jwX","radioOptionActionsContainer":"perseus_5aWP3vgw","buttonRow":"perseus_ezHjicvY"};
1855
1850
 
@@ -1868,7 +1863,7 @@ const boxStyle={width:sizing.size_560,justifyContent:"center",boxSizing:"border-
1868
1863
 
1869
1864
  const RadioOptionSettings=React.forwardRef(function RadioOptionSettings({index,choice,multipleSelect,onStatusChange,onContentChange,onRationaleChange,showDelete,showMove,onDelete,onMove,editingDisabled},ref){const{content,rationale,correct,isNoneOfTheAbove}=choice;const uniqueId=React.useId();const rationaleTextAreaId=`${uniqueId}-rationale-textarea`;const contentEditorRef=React.useRef(null);React.useImperativeHandle(ref,()=>({focus:()=>{contentEditorRef.current?.focus();}}));return jsxRuntimeExports.jsxs("div",{className:styles$2.tile,children:[jsxRuntimeExports.jsx("fieldset",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:styles$2.statusRow,children:[jsxRuntimeExports.jsx(RadioStatusPill,{index:index,correct:correct,multipleSelect:multipleSelect}),jsxRuntimeExports.jsx(BodyText,{size:"small",weight:"bold",tag:"span",children:"Status"}),jsxRuntimeExports.jsx(SegmentedControl,{"aria-label":"Choice status",selectedValue:correct?"correct":"incorrect",onChange:value=>{onStatusChange(index,value==="correct");},options:[{value:"correct",label:"Correct"},{value:"incorrect",label:"Incorrect"}],disabled:editingDisabled})]})}),jsxRuntimeExports.jsx(RadioOptionContentAndImageEditor,{ref:contentEditorRef,content:content,choiceIndex:index,isNoneOfTheAbove:isNoneOfTheAbove??false,onContentChange:onContentChange,editingDisabled:editingDisabled}),jsxRuntimeExports.jsx(BodyText,{size:"small",weight:"bold",tag:"label",htmlFor:rationaleTextAreaId,style:{marginBlockStart:sizing.size_040,marginBlockEnd:sizing.size_040},children:"Rationale"}),jsxRuntimeExports.jsx(TextArea,{id:rationaleTextAreaId,value:rationale??"",placeholder:`Why is this choice ${correct?"correct":"incorrect"}?`,onChange:value=>{onRationaleChange(index,value);},autoResize:true,disabled:editingDisabled}),jsxRuntimeExports.jsx(RadioOptionSettingsActions,{content:content,showDelete:showDelete,showMove:showMove,onDelete:onDelete,onMove:movement=>onMove(index,movement),editingDisabled:editingDisabled})]})});
1870
1865
 
1871
- class RadioEditor extends React.Component{componentDidMount(){if(this.props.multipleSelect&&this.props.countChoices){this.props.onChange({numCorrect:deriveNumCorrect(this.props.choices)});}const needsIdUpdate=this.props.choices.some(choice=>!choice.id||choice.id.trim()==="");if(needsIdUpdate){const updatedChoices=this.props.choices.map((choice,index)=>({...choice,id:this.ensureValidIds(choice.id,index)}));this.props.onChange({choices:updatedChoices});}}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);const isEditingDisabled=this.props.apiOptions.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Randomize order",checked:this.props.randomize,disabled:isEditingDisabled,onChange:value=>{this.props.onChange({randomize:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Multiple selections",checked:this.props.multipleSelect,disabled:isEditingDisabled,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,disabled:isEditingDisabled,onChange:value=>{this.onCountChoicesChange({countChoices:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsxs(BodyText,{size:"xsmall",tag:"span",children:["Current number correct: ",numCorrect]})]})]}),this.props.choices.map((choice,index)=>jsxRuntimeExports.jsx(RadioOptionSettings,{ref:this.getChoiceRef(choice.id),index:index,choice:choice,multipleSelect:this.props.multipleSelect,onStatusChange:this.onStatusChange,onContentChange:this.onContentChange,onRationaleChange:this.onRationaleChange,showDelete:this.props.choices.length>=2,showMove:this.props.choices.length>1&&!choice.isNoneOfTheAbove,onDelete:()=>this.onDelete(index),onMove:this.handleMove,editingDisabled:isEditingDisabled},`choice-${choice.id}`)),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"},disabled:isEditingDisabled,children:"Add a choice"}),!this.props.hasNoneOfTheAbove&&jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:plusIcon,onClick:this.addChoice.bind(this,true),disabled:isEditingDisabled,children:"None of the above"})]})]})}constructor(...args){super(...args),this.choiceRefs=new Map,this.getChoiceRef=choiceId=>{if(!this.choiceRefs.has(choiceId)){this.choiceRefs.set(choiceId,React.createRef());}return this.choiceRefs.get(choiceId)},this.onMultipleSelectChange=options=>{const isMultipleSelect=options.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=options=>{const countChoices=options.countChoices;this.props.onChange({countChoices});},this.generateChoiceId=index=>{return `radio-choice-${index}`},this.ensureValidIds=(choiceId,index)=>{if(!choiceId||choiceId.trim()===""){return this.generateChoiceId(index)}return choiceId},this.onChange=({checked})=>{const choices=this.props.choices.map((choice,i)=>{return {...choice,correct:checked[i],content:choice.isNoneOfTheAbove&&!checked[i]?"":choice.content,id:this.ensureValidIds(choice.id,i)}});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];this.choiceRefs.delete(deleted.id);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:"",id:crypto.randomUUID()};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.getChoiceRef(newChoice.id).current?.focus();});},this.handleMove=(choiceIndex,movement)=>{const newChoices=getMovedChoices(this.props.choices,this.props.hasNoneOfTheAbove,choiceIndex,movement);this.props.onChange({choices:newChoices});},this.focus=()=>{const firstChoice=this.props.choices[0];if(firstChoice?.id){this.getChoiceRef(firstChoice.id).current?.focus();}return true},this.getSaveWarnings=()=>{if(!this.props.choices.some(choice=>choice.correct)){return ["No choice is marked as correct."]}return []};}}RadioEditor.widgetName="radio";RadioEditor.bestPractices={url:"https://www.khanacademy.org/internal-courses/content-creation-best-practices/xe46daa512cd9c644:question-writing/xe46daa512cd9c644:multiple-choice/a/stems",label:"Multiple choice best practices"};RadioEditor.defaultProps=radioLogic.defaultWidgetOptions;
1866
+ class RadioEditor extends React.Component{componentDidMount(){if(this.props.multipleSelect&&this.props.countChoices){this.props.onChange({numCorrect:deriveNumCorrect(this.props.choices)});}const needsIdUpdate=this.props.choices.some(choice=>!choice.id||choice.id.trim()==="");if(needsIdUpdate){const updatedChoices=this.props.choices.map((choice,index)=>({...choice,id:this.ensureValidIds(choice.id,index)}));this.props.onChange({choices:updatedChoices});}}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);const isEditingDisabled=this.props.apiOptions.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Randomize order",checked:this.props.randomize,disabled:isEditingDisabled,onChange:value=>{this.props.onChange({randomize:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Multiple selections",checked:this.props.multipleSelect,disabled:isEditingDisabled,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,disabled:isEditingDisabled,onChange:value=>{this.onCountChoicesChange({countChoices:value});},style:{marginBlockEnd:sizing.size_060}}),jsxRuntimeExports.jsxs(BodyText,{size:"xsmall",tag:"span",children:["Current number correct: ",numCorrect]})]})]}),this.props.choices.map((choice,index)=>jsxRuntimeExports.jsx(RadioOptionSettings,{ref:this.getChoiceRef(choice.id),index:index,choice:choice,multipleSelect:this.props.multipleSelect,onStatusChange:this.onStatusChange,onContentChange:this.onContentChange,onRationaleChange:this.onRationaleChange,showDelete:this.props.choices.length>=2,showMove:this.props.choices.length>1&&!choice.isNoneOfTheAbove,onDelete:()=>this.onDelete(index),onMove:this.handleMove,editingDisabled:isEditingDisabled},`choice-${choice.id}`)),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"},disabled:isEditingDisabled,children:"Add a choice"}),!this.props.hasNoneOfTheAbove&&jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:plusIcon,onClick:this.addChoice.bind(this,true),disabled:isEditingDisabled,children:"None of the above"})]})]})}constructor(...args){super(...args),this.choiceRefs=new Map,this.getChoiceRef=choiceId=>{if(!this.choiceRefs.has(choiceId)){this.choiceRefs.set(choiceId,React.createRef());}return this.choiceRefs.get(choiceId)},this.onMultipleSelectChange=options=>{const isMultipleSelect=options.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=options=>{const countChoices=options.countChoices;this.props.onChange({countChoices});},this.generateChoiceId=index=>{return `radio-choice-${index}`},this.ensureValidIds=(choiceId,index)=>{if(!choiceId||choiceId.trim()===""){return this.generateChoiceId(index)}return choiceId},this.onChange=({checked})=>{const choices=this.props.choices.map((choice,i)=>{return {...choice,correct:checked[i],content:choice.isNoneOfTheAbove&&!checked[i]?"":choice.content,id:this.ensureValidIds(choice.id,i)}});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];this.choiceRefs.delete(deleted.id);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:"",id:crypto.randomUUID()};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.getChoiceRef(newChoice.id).current?.focus();});},this.handleMove=(choiceIndex,movement)=>{const newChoices=getMovedChoices(this.props.choices,this.props.hasNoneOfTheAbove,choiceIndex,movement);this.props.onChange({choices:newChoices});},this.focus=()=>{const firstChoice=this.props.choices[0];if(firstChoice?.id){this.getChoiceRef(firstChoice.id).current?.focus();}return true},this.getSaveWarnings=()=>{if(!this.props.choices.some(choice=>choice.correct)){return ["No choice is marked as correct."]}return []};}}RadioEditor.bestPractices={url:"https://www.khanacademy.org/internal-courses/content-creation-best-practices/xe46daa512cd9c644:question-writing/xe46daa512cd9c644:multiple-choice/a/stems",label:"Multiple choice best practices"};RadioEditor.defaultProps=radioLogic.defaultWidgetOptions;
1872
1867
 
1873
1868
  var styles$1 = {"card":"perseus_j1ydPJka"};
1874
1869
 
@@ -1876,15 +1871,15 @@ const cardInputStyle={flexGrow:1};function CardEditor({index,value,isFirst,isLas
1876
1871
 
1877
1872
  var styles = {"editor":"perseus_nJ-Uq5eT","section":"perseus_vTiphIsj","cards":"perseus_xhRr18kA","addCard":"perseus_cwHzt54c"};
1878
1873
 
1879
- const maxCards=10;const minCards=2;const defaultOptions=sorterLogic.defaultWidgetOptions;const layoutOptions={horizontal:"Horizontal",vertical:"Vertical"};const SorterEditor=React.forwardRef(function SorterEditor({correct=defaultOptions.correct,layout=defaultOptions.layout,padding=defaultOptions.padding,onChange},ref){React.useImperativeHandle(ref,()=>({serialize:()=>{return {correct,layout,padding}},getSaveWarnings:()=>{const warnings=[];if(correct.length<minCards){warnings.push(`Sorter requires at least ${minCards} cards.`);}if(correct.some(card=>card.trim()==="")){warnings.push("Sorter cards cannot be blank.");}return warnings}}),[correct,layout,padding]);const onCardChange=(index,value)=>{const newCorrect=[...correct];newCorrect[index]=value;onChange({correct:newCorrect});};const onAddCard=()=>{if(correct.length>=maxCards){return}onChange({correct:[...correct,""]});};const onMoveCard=(index,offset)=>{const newCorrect=[...correct];const newIndex=index+offset;[newCorrect[index],newCorrect[newIndex]]=[newCorrect[newIndex],newCorrect[index]];onChange({correct:newCorrect});};const onDeleteCard=index=>{onChange({correct:correct.filter((card,i)=>i!==index)});};return jsxRuntimeExports.jsxs(View,{className:styles.editor,children:[jsxRuntimeExports.jsxs(View,{className:styles.section,children:[jsxRuntimeExports.jsxs("div",{children:["Correct answer"," ",jsxRuntimeExports.jsxs(InfoTip,{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("p",{children:"For horizontal orientation, the top input represents the leftmost card and the bottom input represents the rightmost card."})]})]}),jsxRuntimeExports.jsx(View,{tag:"ol",className:styles.cards,children:correct.map((card,i)=>jsxRuntimeExports.jsx(CardEditor,{index:i,value:card,isFirst:i===0,isLast:i===correct.length-1,onChange:value=>onCardChange(i,value),onMoveUp:()=>onMoveCard(i,-1),onMoveDown:()=>onMoveCard(i,1),onDelete:()=>onDeleteCard(i)},i))}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,className:styles.addCard,disabled:correct.length>=maxCards,onClick:onAddCard,children:"Add a card"})]}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Layout",field:jsxRuntimeExports.jsx(TypedSingleSelect,{options:layoutOptions,selectedValue:layout,onChange:newLayout=>onChange({layout:newLayout})})}),jsxRuntimeExports.jsx(InfoTip,{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:padding,onChange:value=>{onChange({padding:value});}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Padding is good for text, but not needed for images."})})]})]})});var SorterEditor$1 = Object.assign(SorterEditor,{widgetName:"sorter",defaultProps:defaultOptions});
1874
+ const maxCards=10;const minCards=2;const defaultOptions=sorterLogic.defaultWidgetOptions;const layoutOptions={horizontal:"Horizontal",vertical:"Vertical"};const SorterEditor=React.forwardRef(function SorterEditor({correct=defaultOptions.correct,layout=defaultOptions.layout,padding=defaultOptions.padding,onChange},ref){React.useImperativeHandle(ref,()=>({serialize:()=>{return {correct,layout,padding}},getSaveWarnings:()=>{const warnings=[];if(correct.length<minCards){warnings.push(`Sorter requires at least ${minCards} cards.`);}if(correct.some(card=>card.trim()==="")){warnings.push("Sorter cards cannot be blank.");}return warnings}}),[correct,layout,padding]);const onCardChange=(index,value)=>{const newCorrect=[...correct];newCorrect[index]=value;onChange({correct:newCorrect});};const onAddCard=()=>{if(correct.length>=maxCards){return}onChange({correct:[...correct,""]});};const onMoveCard=(index,offset)=>{const newCorrect=[...correct];const newIndex=index+offset;[newCorrect[index],newCorrect[newIndex]]=[newCorrect[newIndex],newCorrect[index]];onChange({correct:newCorrect});};const onDeleteCard=index=>{onChange({correct:correct.filter((card,i)=>i!==index)});};return jsxRuntimeExports.jsxs(View,{className:styles.editor,children:[jsxRuntimeExports.jsxs(View,{className:styles.section,children:[jsxRuntimeExports.jsxs("div",{children:["Correct answer"," ",jsxRuntimeExports.jsxs(InfoTip,{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("p",{children:"For horizontal orientation, the top input represents the leftmost card and the bottom input represents the rightmost card."})]})]}),jsxRuntimeExports.jsx(View,{tag:"ol",className:styles.cards,children:correct.map((card,i)=>jsxRuntimeExports.jsx(CardEditor,{index:i,value:card,isFirst:i===0,isLast:i===correct.length-1,onChange:value=>onCardChange(i,value),onMoveUp:()=>onMoveCard(i,-1),onMoveDown:()=>onMoveCard(i,1),onDelete:()=>onDeleteCard(i)},i))}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",startIcon:plusCircle,className:styles.addCard,disabled:correct.length>=maxCards,onClick:onAddCard,children:"Add a card"})]}),jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Layout",field:jsxRuntimeExports.jsx(TypedSingleSelect,{options:layoutOptions,selectedValue:layout,onChange:newLayout=>onChange({layout:newLayout})})}),jsxRuntimeExports.jsx(InfoTip,{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:padding,onChange:value=>{onChange({padding:value});}}),jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"Padding is good for text, but not needed for images."})})]})]})});var SorterEditor$1 = Object.assign(SorterEditor,{defaultProps:defaultOptions});
1880
1875
 
1881
- const{NumberInput}=components;const Table=TableWidget.widget;class TableEditor extends React.Component{render(){const tableProps={options:{headers:this.props.headers,rows:this.props.rows,columns:this.props.columns,answers:this.props.answers},onChange:this.props.onChange,userInput:this.props.answers,handleUserInput:userInput=>{if(this.props.apiOptions?.editingDisabled){return}this.props.onChange({answers:userInput});},apiOptions:this.props.apiOptions,editableHeaders:true,onFocus:()=>{},onBlur:()=>{},trackInteraction:()=>{},Editor:Editor};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Number of columns:"," ",jsxRuntimeExports.jsx(NumberInput,{ref:this.numberOfColumns,value:this.props.columns,onChange:val=>{if(val){this.onSizeInput(this.props.rows,val);}},useArrowKeys:true})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Number of rows:"," ",jsxRuntimeExports.jsx(NumberInput,{ref:"numberOfRows",value:this.props.rows,onChange:val=>{if(val){this.onSizeInput(val,this.props.columns);}},useArrowKeys:true})]})}),jsxRuntimeExports.jsxs("div",{children:[" ","Table of answers:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"The student has to fill out all cells in the table. For partially filled tables create a table using the template, and insert text input boxes as desired."})})]}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(Table,{...tableProps})})]})}constructor(...args){super(...args),this.numberOfColumns=React.createRef(),this.focus=()=>{this.numberOfColumns.current?.focus();},this.onSizeInput=(numRawRows,numRawColumns)=>{let rows=+numRawRows||0;let columns=+numRawColumns||0;rows=Math.min(Math.max(1,rows),30);columns=Math.min(Math.max(1,columns),6);const oldColumns=this.props.columns;const oldRows=this.props.rows;const answers=this.props.answers;if(rows<=oldRows){answers.length=rows;}else {_(rows-oldRows).times(function(){answers.push(Util.stringArrayOfSize(oldColumns));});}function fixColumnSizing(array){if(columns<=oldColumns){array.length=columns;}else {_(columns-oldColumns).times(function(){array.push("");});}}const headers=this.props.headers;fixColumnSizing(headers);_.each(answers,fixColumnSizing);this.props.onChange({rows:rows,columns:columns,answers:answers,headers:headers});},this.serialize=()=>{const json=_.pick(this.props,"headers","rows","columns");return _.extend({},json,{answers:this.props.answers.map(_.clone)})};}}TableEditor.propTypes={rows:PropTypes.number,columns:PropTypes.number,headers:PropTypes.arrayOf(PropTypes.string),answers:PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string))};TableEditor.widgetName="table";TableEditor.defaultProps=tableLogic.defaultWidgetOptions;
1876
+ const{NumberInput}=components;const Table=TableWidget.widget;class TableEditor extends React.Component{render(){const tableProps={options:{headers:this.props.headers,rows:this.props.rows,columns:this.props.columns,answers:this.props.answers},onChange:this.props.onChange,userInput:this.props.answers,handleUserInput:userInput=>{if(this.props.apiOptions?.editingDisabled){return}this.props.onChange({answers:userInput});},apiOptions:this.props.apiOptions,editableHeaders:true,onFocus:()=>{},onBlur:()=>{},trackInteraction:()=>{},Editor:Editor};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Number of columns:"," ",jsxRuntimeExports.jsx(NumberInput,{ref:this.numberOfColumns,value:this.props.columns,onChange:val=>{if(val){this.onSizeInput(this.props.rows,val);}},useArrowKeys:true})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("label",{children:["Number of rows:"," ",jsxRuntimeExports.jsx(NumberInput,{ref:"numberOfRows",value:this.props.rows,onChange:val=>{if(val){this.onSizeInput(val,this.props.columns);}},useArrowKeys:true})]})}),jsxRuntimeExports.jsxs("div",{children:[" ","Table of answers:"," ",jsxRuntimeExports.jsx(InfoTip,{children:jsxRuntimeExports.jsx("p",{children:"The student has to fill out all cells in the table. For partially filled tables create a table using the template, and insert text input boxes as desired."})})]}),jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(Table,{...tableProps})})]})}constructor(...args){super(...args),this.numberOfColumns=React.createRef(),this.focus=()=>{this.numberOfColumns.current?.focus();},this.onSizeInput=(numRawRows,numRawColumns)=>{let rows=+numRawRows||0;let columns=+numRawColumns||0;rows=Math.min(Math.max(1,rows),30);columns=Math.min(Math.max(1,columns),6);const oldColumns=this.props.columns;const oldRows=this.props.rows;const answers=this.props.answers;if(rows<=oldRows){answers.length=rows;}else {_(rows-oldRows).times(function(){answers.push(Util.stringArrayOfSize(oldColumns));});}function fixColumnSizing(array){if(columns<=oldColumns){array.length=columns;}else {_(columns-oldColumns).times(function(){array.push("");});}}const headers=this.props.headers;fixColumnSizing(headers);_.each(answers,fixColumnSizing);this.props.onChange({rows:rows,columns:columns,answers:answers,headers:headers});},this.serialize=()=>{const json=_.pick(this.props,"headers","rows","columns");return _.extend({},json,{answers:this.props.answers.map(_.clone)})};}}TableEditor.propTypes={rows:PropTypes.number,columns:PropTypes.number,headers:PropTypes.arrayOf(PropTypes.string),answers:PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string))};TableEditor.defaultProps=tableLogic.defaultWidgetOptions;
1882
1877
 
1883
1878
  const KA_VIDEO_URL=/khanacademy\.org\/.*\/v\/(.*)$/;function getSlugFromUrl(url){const match=KA_VIDEO_URL.exec(url);if(match){return match[1]}return url}function VideoSettings(props){const[inputValue,setInputValue]=React.useState(props.location);function handleUrlChange(url){props.onChange({location:getSlugFromUrl(url)});}return jsxRuntimeExports.jsx(LabeledField,{label:"KA Video Slug",description:"KA video URLs will be converted to just the slug.",field:jsxRuntimeExports.jsx(TextArea,{value:inputValue,onChange:setInputValue,onBlur:e=>handleUrlChange(e.target.value),autoResize:true})})}
1884
1879
 
1885
- class VideoEditor extends React.Component{render(){return jsxRuntimeExports.jsx(VideoSettings,{...this.props})}constructor(...args){super(...args),this.serialize=()=>{return {location:this.props.location}};}}VideoEditor.widgetName="video";VideoEditor.defaultProps=videoLogic.defaultWidgetOptions;
1880
+ class VideoEditor extends React.Component{render(){return jsxRuntimeExports.jsx(VideoSettings,{...this.props})}constructor(...args){super(...args),this.serialize=()=>{return {location:this.props.location}};}}VideoEditor.defaultProps=videoLogic.defaultWidgetOptions;
1886
1881
 
1887
- var AllEditors = [CategorizerEditor,CSProgramEditor,DefinitionEditor,DropdownEditor,ExplanationEditor,ExpressionEditor,FreeResponseEditor,GradedGroupEditor,GradedGroupSetEditor,GrapherEditor,GroupEditor,IframeEditor,ImageEditor,InputNumberEditor,InteractionEditor,InteractiveGraphEditor,LabelImageEditor,MatcherEditor,MatrixEditor,MeasurerEditor,NumberLineEditor,NumericInputEditor,OrdererEditor,PhetSimulationEditor,PlotterEditor,PythonProgramEditor,SorterEditor$1,TableEditor,VideoEditor,RadioEditor,DeprecatedStandinEditor];
1882
+ var AllEditors = {categorizer:CategorizerEditor,"cs-program":CSProgramEditor,definition:DefinitionEditor,"deprecated-standin":DeprecatedStandinEditor,dropdown:DropdownEditor,explanation:ExplanationEditor,expression:ExpressionEditor,"free-response":FreeResponseEditor,"graded-group":GradedGroupEditor,"graded-group-set":GradedGroupSetEditor,grapher:GrapherEditor,group:GroupEditor,iframe:IframeEditor,image:ImageEditor,"input-number":InputNumberEditor,interaction:InteractionEditor,"interactive-graph":InteractiveGraphEditor,"label-image":LabelImageEditor,matcher:MatcherEditor,matrix:MatrixEditor,measurer:MeasurerEditor,"number-line":NumberLineEditor,"numeric-input":NumericInputEditor,orderer:OrdererEditor,"phet-simulation":PhetSimulationEditor,plotter:PlotterEditor,"python-program":PythonProgramEditor,radio:RadioEditor,sorter:SorterEditor$1,table:TableEditor,video:VideoEditor};
1888
1883
 
1889
1884
  Widgets.registerEditors(AllEditors);Widgets.registerWidgets(widgets);Widgets.replaceDeprecatedWidgets();Widgets.replaceDeprecatedEditors();
1890
1885