@khanacademy/perseus-editor 44.0.2 → 44.0.3

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.
@@ -28,7 +28,7 @@ declare class WidgetEditor extends React.Component<Props, State> {
28
28
  _handleAlignmentChange: (newAlignment: Alignment) => void;
29
29
  getSaveWarnings: () => unknown;
30
30
  serialize: () => {
31
- type: "iframe" | "table" | "video" | "image" | "radio" | "definition" | "group" | "blank" | "categorizer" | "cs-program" | "dropdown" | "explanation" | "expression" | "fill-in-the-blank" | "free-response" | "grapher" | "graded-group-set" | "graded-group" | "input-number" | "interaction" | "interactive-graph" | "label-image" | "matcher" | "matrix" | "measurer" | "number-line" | "numeric-input" | "orderer" | "phet-simulation" | "python-program" | "plotter" | "sorter" | "mock-widget" | "deprecated-standin";
31
+ type: "iframe" | "table" | "video" | "image" | "radio" | "definition" | "group" | "blank" | "categorizer" | "cs-program" | "dropdown" | "explanation" | "expression" | "fill-in-the-blank" | "free-response" | "grapher" | "graded-group-set" | "graded-group" | "input-number" | "interaction" | "interactive-graph" | "label-image" | "matcher" | "matrix" | "measurer" | "number-line" | "numeric-input" | "orderer" | "phet-simulation" | "python-program" | "plotter" | "sorter" | "molecule-renderer" | "passage-ref-target" | "passage-ref" | "passage" | "lights-puzzle" | "sequence" | "simulator" | "transformer" | "mock-widget";
32
32
  alignment: Alignment | undefined;
33
33
  static: boolean | undefined;
34
34
  graded: boolean | undefined;
package/dist/index.js CHANGED
@@ -66,7 +66,7 @@ import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
66
66
  import arrowDown from '@phosphor-icons/core/regular/arrow-down.svg';
67
67
  import arrowUp from '@phosphor-icons/core/regular/arrow-up.svg';
68
68
 
69
- const libName="@khanacademy/perseus-editor";const libVersion="44.0.2";addLibraryVersionToPerseusDebug(libName,libVersion);
69
+ const libName="@khanacademy/perseus-editor";const libVersion="44.0.3";addLibraryVersionToPerseusDebug(libName,libVersion);
70
70
 
71
71
  var jsxRuntime = {exports: {}};
72
72
 
@@ -1627,27 +1627,27 @@ const{ButtonGroup: ButtonGroup$4}=components;class DashPicker extends React.Comp
1627
1627
 
1628
1628
  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}});
1629
1629
 
1630
- 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};
1630
+ const{NumberInput: NumberInput$a}=components;class FunctionEditor extends React.Component{handleChange(changes){this.props.onChange({value:this.props.value,funcName:this.props.funcName,rangeMin:this.props.rangeMin,rangeMax:this.props.rangeMax,color:this.props.color,strokeDasharray:this.props.strokeDasharray,strokeWidth:this.props.strokeWidth,...changes});}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:value=>this.handleChange({value})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Range: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.rangeMin,onChange:rangeMin=>this.handleChange({rangeMin})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.rangeMax,onChange:rangeMax=>this.handleChange({rangeMax})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:color=>this.handleChange({color})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(DashPicker,{value:this.props.strokeDasharray,onChange:strokeDasharray=>this.handleChange({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:strokeWidth=>this.handleChange({strokeWidth})})]})})]})}}FunctionEditor.defaultProps={value:"x",funcName:"f",rangeMin:"-10",rangeMax:"10",color:KhanColors.BLUE,strokeDasharray:"",strokeWidth:2};
1631
1631
 
1632
- const{TextInput: TextInput$1}=components;class LabelEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(TextInput$1,{value:this.props.label,onChange:this.change("label"),style:{width:"100%"}})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Location: ",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.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:this.change("color")})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}LabelEditor.defaultProps={coordX:"0",coordY:"0",color:KhanColors.BLACK,label:"\\phi"};
1632
+ const{TextInput: TextInput$1}=components;class LabelEditor extends React.Component{handleChange(changes){this.props.onChange({label:this.props.label,color:this.props.color,coordX:this.props.coordX,coordY:this.props.coordY,...changes});}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(TextInput$1,{value:this.props.label,onChange:label=>this.handleChange({label}),style:{width:"100%"}})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Location: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordX,onChange:coordX=>this.handleChange({coordX})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordY,onChange:coordY=>this.handleChange({coordY})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:color=>this.handleChange({color})})})]})}}LabelEditor.defaultProps={coordX:"0",coordY:"0",color:KhanColors.BLACK,label:"\\phi"};
1633
1633
 
1634
1634
  const{ButtonGroup: ButtonGroup$3}=components;class ArrowPicker extends React.Component{render(){return jsxRuntimeExports.jsx(ButtonGroup$3,{value:this.props.value,buttons:[{value:"",content:jsxRuntimeExports.jsx("span",{children:"—"})},{value:"->",content:jsxRuntimeExports.jsx("span",{children:"→"})}],onChange:this.props.onChange})}}ArrowPicker.defaultProps={value:""};
1635
1635
 
1636
- const{NumberInput: NumberInput$9}=components;class LineEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startX,onChange:this.change("startX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startY,onChange:this.change("startY")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["End: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endX,onChange:this.change("endX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endY,onChange:this.change("endY")}),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.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(DashPicker,{value:this.props.strokeDasharray,onChange:this.change("strokeDasharray")}),"   ",jsxRuntimeExports.jsx(ArrowPicker,{value:this.props.arrows,onChange:this.change("arrows")})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:["Width:"," ",jsxRuntimeExports.jsx(NumberInput$9,{value:this.props.strokeWidth,placeholder:2,onChange:this.change("strokeWidth")})]})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}LineEditor.defaultProps={startX:"-5",startY:"5",endX:"5",endY:"5",color:KhanColors.BLACK,strokeDasharray:"",arrows:"",strokeWidth:2};
1636
+ const{NumberInput: NumberInput$9}=components;class LineEditor extends React.Component{handleChange(changes){this.props.onChange({startX:this.props.startX,startY:this.props.startY,endX:this.props.endX,endY:this.props.endY,color:this.props.color,strokeDasharray:this.props.strokeDasharray,arrows:this.props.arrows,strokeWidth:this.props.strokeWidth,...changes});}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startX,onChange:this.change("startX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startY,onChange:this.change("startY")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["End: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endX,onChange:this.change("endX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endY,onChange:this.change("endY")}),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.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(DashPicker,{value:this.props.strokeDasharray,onChange:this.change("strokeDasharray")}),"   ",jsxRuntimeExports.jsx(ArrowPicker,{value:this.props.arrows,onChange:this.change("arrows")})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:["Width:"," ",jsxRuntimeExports.jsx(NumberInput$9,{value:this.props.strokeWidth,placeholder:2,onChange:this.change("strokeWidth")})]})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}LineEditor.defaultProps={startX:"-5",startY:"5",endX:"5",endY:"5",color:KhanColors.BLACK,strokeDasharray:"",arrows:"",strokeWidth:2};
1637
1637
 
1638
- const{ButtonGroup: ButtonGroup$2,NumberInput: NumberInput$8}=components;class ConstraintEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Constraint:"," ",jsxRuntimeExports.jsx(ButtonGroup$2,{value:this.props.constraint,buttons:[{value:"none",content:"None"},{value:"snap",content:"Snap"},{value:"x",content:"x="},{value:"y",content:"y="}],onChange:this.change("constraint")})]}),this.props.constraint==="snap"&&jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Snap:"," ",jsxRuntimeExports.jsx(NumberInput$8,{value:this.props.snap,placeholder:0,onChange:this.change("snap")})]}),this.props.constraint==="x"&&jsxRuntimeExports.jsx("div",{className:"graph-settings",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"x="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintFn,onChange:this.change("constraintFn")})]})}),this.props.constraint==="y"&&jsxRuntimeExports.jsx("div",{className:"graph-settings",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"y="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintFn,onChange:this.change("constraintFn")})]})}),"Ensure these are set so nothing can be dragged off the canvas:",jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"x \\in \\Large["})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintXMin,onChange:this.change("constraintXMin")}),jsxRuntimeExports.jsx(TeX,{children:", "})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintXMax,onChange:this.change("constraintXMax")})," ",jsxRuntimeExports.jsx(TeX,{children:"\\Large]"})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"y \\in \\Large["})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintYMin,onChange:this.change("constraintYMin")}),jsxRuntimeExports.jsx(TeX,{children:", "})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintYMax,onChange:this.change("constraintYMax")})," ",jsxRuntimeExports.jsx(TeX,{children:"\\Large]"})]})})]})}constructor(...args){super(...args),this.change=propName=>{return deprecatedChangeableChange.call(this,propName)};}}ConstraintEditor.defaultProps={constraint:"none",snap:.5,constraintFn:"0",constraintXMin:"-10",constraintXMax:"10",constraintYMin:"-10",constraintYMax:"10"};
1638
+ const{ButtonGroup: ButtonGroup$2,NumberInput: NumberInput$8}=components;class ConstraintEditor extends React.Component{handleChange(changes){this.props.onChange({constraint:this.props.constraint,constraintFn:this.props.constraintFn,constraintXMax:this.props.constraintXMax,constraintXMin:this.props.constraintXMin,constraintYMax:this.props.constraintYMax,constraintYMin:this.props.constraintYMin,snap:this.props.snap,...changes});}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Constraint:"," ",jsxRuntimeExports.jsx(ButtonGroup$2,{value:this.props.constraint,buttons:[{value:"none",content:"None"},{value:"snap",content:"Snap"},{value:"x",content:"x="},{value:"y",content:"y="}],onChange:constraint=>this.handleChange({constraint})})]}),this.props.constraint==="snap"&&jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Snap:"," ",jsxRuntimeExports.jsx(NumberInput$8,{value:this.props.snap,placeholder:0,onChange:snap=>this.handleChange({snap})})]}),this.props.constraint==="x"&&jsxRuntimeExports.jsx("div",{className:"graph-settings",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"x="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintFn,onChange:constraintFn=>this.handleChange({constraintFn})})]})}),this.props.constraint==="y"&&jsxRuntimeExports.jsx("div",{className:"graph-settings",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"y="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintFn,onChange:constraintFn=>this.handleChange({constraintFn})})]})}),"Ensure these are set so nothing can be dragged off the canvas:",jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"x \\in \\Large["})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintXMin,onChange:constraintXMin=>this.handleChange({constraintXMin})}),jsxRuntimeExports.jsx(TeX,{children:", "})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintXMax,onChange:constraintXMax=>this.handleChange({constraintXMax})})," ",jsxRuntimeExports.jsx(TeX,{children:"\\Large]"})]})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"y \\in \\Large["})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintYMin,onChange:constraintYMin=>this.handleChange({constraintYMin})}),jsxRuntimeExports.jsx(TeX,{children:", "})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.constraintYMax,onChange:constraintYMax=>this.handleChange({constraintYMax})})," ",jsxRuntimeExports.jsx(TeX,{children:"\\Large]"})]})})]})}}ConstraintEditor.defaultProps={constraint:"none",snap:.5,constraintFn:"0",constraintXMin:"-10",constraintXMax:"10",constraintYMin:"-10",constraintYMax:"10"};
1639
1639
 
1640
- const{NumberInput: NumberInput$7}=components;class MovableLineEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:["Initial position:",jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startX,onChange:this.change("startX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startY,onChange:this.change("startY")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["End: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endX,onChange:this.change("endX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endY,onChange:this.change("endY")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start updates ",jsxRuntimeExports.jsx(TeX,{children:"(x_n, y_n)"})," for ",jsxRuntimeExports.jsx(TeX,{children:"n ="}),jsxRuntimeExports.jsx(NumberInput$7,{value:this.props.startSubscript,placeholder:0,onChange:this.change("startSubscript")})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["End updates ",jsxRuntimeExports.jsx(TeX,{children:"(x_m, y_m)"})," for ",jsxRuntimeExports.jsx(TeX,{children:"m ="}),jsxRuntimeExports.jsx(NumberInput$7,{value:this.props.endSubscript,placeholder:0,onChange:this.change("endSubscript")})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:"All constraints are applied to the start point."}),jsxRuntimeExports.jsx(ConstraintEditor,{...this.props})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}MovableLineEditor.defaultProps={startX:"-5",startY:"5",endX:"5",endY:"5",constraint:"none",snap:.5,constraintFn:"0",constraintXMin:"-10",constraintXMax:"10",constraintYMin:"-10",constraintYMax:"10"};
1640
+ const{NumberInput: NumberInput$7}=components;class MovableLineEditor extends React.Component{handleChange(changes){this.props.onChange({startX:this.props.startX,startY:this.props.startY,endX:this.props.endX,endY:this.props.endY,constraint:this.props.constraint,snap:this.props.snap,constraintFn:this.props.constraintFn,constraintXMin:this.props.constraintXMin,constraintXMax:this.props.constraintXMax,constraintYMin:this.props.constraintYMin,constraintYMax:this.props.constraintYMax,startSubscript:this.props.startSubscript,endSubscript:this.props.endSubscript,...changes});}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:["Initial position:",jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startX,onChange:startX=>this.handleChange({startX})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startY,onChange:startY=>this.handleChange({startY})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["End: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endX,onChange:endX=>this.handleChange({endX})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.endY,onChange:endY=>this.handleChange({endY})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start updates ",jsxRuntimeExports.jsx(TeX,{children:"(x_n, y_n)"})," for ",jsxRuntimeExports.jsx(TeX,{children:"n ="}),jsxRuntimeExports.jsx(NumberInput$7,{value:this.props.startSubscript,placeholder:0,onChange:startSubscript=>this.handleChange({startSubscript})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["End updates ",jsxRuntimeExports.jsx(TeX,{children:"(x_m, y_m)"})," for ",jsxRuntimeExports.jsx(TeX,{children:"m ="}),jsxRuntimeExports.jsx(NumberInput$7,{value:this.props.endSubscript,placeholder:0,onChange:endSubscript=>this.handleChange({endSubscript})})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:"All constraints are applied to the start point."}),jsxRuntimeExports.jsx(ConstraintEditor,{...this.props,onChange:constraint=>this.handleChange(constraint)})]})}}MovableLineEditor.defaultProps={startX:"-5",startY:"5",endX:"5",endY:"5",constraint:"none",snap:.5,constraintFn:"0",constraintXMin:"-10",constraintXMax:"10",constraintYMin:"-10",constraintYMax:"10",startSubscript:0,endSubscript:0};
1641
1641
 
1642
- const{NumberInput: NumberInput$6}=components;class MovablePointEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startX,onChange:this.change("startX")}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startY,onChange:this.change("startY")}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Update ",jsxRuntimeExports.jsx(TeX,{children:"(x_n, y_n)"})," for ",jsxRuntimeExports.jsx(TeX,{children:"n ="})," ",jsxRuntimeExports.jsx(NumberInput$6,{value:this.props.varSubscript,placeholder:0,onChange:this.change("varSubscript")})]}),jsxRuntimeExports.jsx(ConstraintEditor,{...this.props})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}MovablePointEditor.defaultProps={startX:"0",startY:"0",constraint:"none",snap:.5,constraintFn:"0",constraintXMin:"-10",constraintXMax:"10",constraintYMin:"-10",constraintYMax:"10"};
1642
+ const{NumberInput: NumberInput$6}=components;class MovablePointEditor extends React.Component{handleChange(options){this.props.onChange({startX:this.props.startX,startY:this.props.startY,constraint:this.props.constraint,snap:this.props.snap,constraintFn:this.props.constraintFn,constraintXMin:this.props.constraintXMin,constraintXMax:this.props.constraintXMax,constraintYMin:this.props.constraintYMin,constraintYMax:this.props.constraintYMax,varSubscript:this.props.varSubscript,...options});}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Start: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startX,onChange:startX=>this.handleChange({startX})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.startY,onChange:startY=>this.handleChange({startY})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Update ",jsxRuntimeExports.jsx(TeX,{children:"(x_n, y_n)"})," for ",jsxRuntimeExports.jsx(TeX,{children:"n ="})," ",jsxRuntimeExports.jsx(NumberInput$6,{value:this.props.varSubscript,placeholder:0,onChange:varSubscript=>this.handleChange({varSubscript})})]}),jsxRuntimeExports.jsx(ConstraintEditor,{...this.props,onChange:constraint=>this.handleChange(constraint)})]})}}MovablePointEditor.defaultProps={startX:"0",startY:"0",constraint:"none",snap:.5,constraintFn:"0",constraintXMin:"-10",constraintXMax:"10",constraintYMin:"-10",constraintYMax:"10",varSubscript:0};
1643
1643
 
1644
- const{NumberInput: NumberInput$5}=components;class ParametricEditor 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:"X(t) ="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.x,onChange:this.change("x")})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"Y(t) ="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.y,onChange:this.change("y")})]}),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$5,{value:this.props.strokeWidth,placeholder:2,onChange:this.change("strokeWidth")})]})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}ParametricEditor.defaultProps={x:"cos(t)",y:"sin(t)",rangeMin:"0",rangeMax:"2\\pi",color:KhanColors.BLUE,strokeDasharray:"",strokeWidth:2};
1644
+ const{NumberInput: NumberInput$5}=components;class ParametricEditor extends React.Component{handleChange(changes){this.props.onChange({x:this.props.x,y:this.props.y,rangeMin:this.props.rangeMin,rangeMax:this.props.rangeMax,color:this.props.color,strokeDasharray:this.props.strokeDasharray,strokeWidth:this.props.strokeWidth,...changes});}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:"X(t) ="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.x,onChange:x=>this.handleChange({x})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(TeX,{children:"Y(t) ="})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.y,onChange:y=>this.handleChange({y})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Range: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.rangeMin,onChange:rangeMin=>this.handleChange({rangeMin})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.rangeMax,onChange:rangeMax=>this.handleChange({rangeMax})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:color=>this.handleChange({color})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(DashPicker,{value:this.props.strokeDasharray,onChange:strokeDasharray=>this.handleChange({strokeDasharray})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-left-col",children:["Width:"," ",jsxRuntimeExports.jsx(NumberInput$5,{value:this.props.strokeWidth,placeholder:2,onChange:strokeWidth=>this.handleChange({strokeWidth})})]})})]})}}ParametricEditor.defaultProps={x:"cos(t)",y:"sin(t)",rangeMin:"0",rangeMax:"2\\pi",color:KhanColors.BLUE,strokeDasharray:"",strokeWidth:2};
1645
1645
 
1646
- class PointEditor extends React.Component{render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Coordinate: ",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.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:this.change("color")})})]})}constructor(...args){super(...args),this.change=(...args)=>{return deprecatedChangeableChange.apply(this,args)};}}PointEditor.defaultProps={coordX:"0",coordY:"0",color:KhanColors.BLACK};
1646
+ class PointEditor extends React.Component{handleChange(changes){this.props.onChange({coordX:this.props.coordX,coordY:this.props.coordY,color:this.props.color,...changes});}render(){const{TeX}=Dependencies.getDependencies();return jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Coordinate: ",jsxRuntimeExports.jsx(TeX,{children:"\\Large("}),jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordX,onChange:coordX=>this.handleChange({coordX})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordY,onChange:coordY=>this.handleChange({coordY})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,onChange:color=>this.handleChange({color})})})]})}}PointEditor.defaultProps={coordX:"0",coordY:"0",color:KhanColors.BLACK};
1647
1647
 
1648
- 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};
1648
+ class RectangleEditor extends React.Component{handleChange(changes){this.props.onChange({coordX:this.props.coordX,coordY:this.props.coordY,width:this.props.width,height:this.props.height,color:this.props.color,...changes});}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:coordX=>this.handleChange({coordX})}),jsxRuntimeExports.jsx(TeX,{children:","})," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.coordY,onChange:coordY=>this.handleChange({coordY})}),jsxRuntimeExports.jsx(TeX,{children:"\\Large)"})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Width:"," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.width,onChange:width=>this.handleChange({width})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:["Height:"," ",jsxRuntimeExports.jsx(MathquillInput,{value:this.props.height,onChange:height=>this.handleChange({height})})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(ColorPicker,{value:this.props.color,lightColors:true,onChange:color=>this.handleChange({color})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:"You want a border? Sorry, draw your own."})]})}}RectangleEditor.defaultProps={coordX:"-5",coordY:"5",width:"2",height:"3",color:KhanColors.LIGHT_BLUE};
1649
1649
 
1650
- 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;
1650
+ const{unescapeMathMode}=Util;class InteractionEditor extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({usedVarSubscripts:this._getAllVarSubscripts(nextProps.elements),usedFunctionNames:this._getAllFunctionNames(nextProps.elements)});}handleChange(changes){this.props.onChange({graph:this.props.graph,elements:this.props.elements,...changes});}handleElementChange(n,newElement){const elementsCopy=[...this.props.elements];elementsCopy[n]=newElement;this.handleChange({elements:elementsCopy});}_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)}nextSubscript(){return Math.max(...this.state.usedVarSubscripts,-1)+1}nextFuncName(){return String.fromCharCode(Math.max(...this.state.usedFunctionNames.map(c=>c.charCodeAt(0)),"e".charCodeAt(0))+1)}createElement(elementType){switch(elementType){case "movable-point":return {type:"movable-point",key:`movable-point-${randomId()}`,options:{...MovablePointEditor.defaultProps,varSubscript:this.nextSubscript()}};case "movable-line":return {type:"movable-line",key:`movable-line-${randomId()}`,options:{...MovableLineEditor.defaultProps,startSubscript:this.nextSubscript(),endSubscript:this.nextSubscript()+1}};case "point":return {type:"point",key:`point-${randomId()}`,options:{...PointEditor.defaultProps}};case "line":return {type:"line",key:`line-${randomId()}`,options:{...LineEditor.defaultProps}};case "function":return {type:"function",key:`function-${randomId()}`,options:{...FunctionEditor.defaultProps,funcName:this.nextFuncName()}};case "parametric":return {type:"parametric",key:`parametric-${randomId()}`,options:{...ParametricEditor.defaultProps}};case "rectangle":return {type:"rectangle",key:`rectangle-${randomId()}`,options:{...RectangleEditor.defaultProps}};case "label":return {type:"label",key:`label-${randomId()}`,options:{...LabelEditor.defaultProps}};default:throw new Error(`Unrecognized element type: ${elementType}`)}}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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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:newOptions=>{this.handleElementChange(n,{...element,options:newOptions});}})},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.handleChange({graph:{...this.props.graph,...rest,tickStep:step}});},this._addNewElement=e=>{const elementType=e.target.value;if(elementType===""){return}e.target.value="";this.handleChange({elements:this.props.elements.concat([this.createElement(elementType)])});},this._deleteElement=index=>{const element=this.props.elements[index];this.handleChange({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.handleChange({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.handleChange({elements:newElements});},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}InteractionEditor.defaultProps=interactionLogic.defaultWidgetOptions;function randomId(){return (Math.random()*0xffffff<<0).toString(16)}
1651
1651
 
1652
1652
  var styles$E = {"singleSelectShort":"perseus_wAZzFxEx","row":"perseus_6FquBkGo"};
1653
1653
 
@@ -1673,7 +1673,7 @@ function AxisTickSwitches(props){const{showAxisTicks,onChange,disabled}=props;re
1673
1673
 
1674
1674
  var styles$B = {"backgroundUrlInput":"perseus_so0nIc4z","checkboxRow":"perseus_lfG1X93S","protractorSection":"perseus_thf-SEbO"};
1675
1675
 
1676
- 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,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,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}};
1676
+ 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;}handleChange(changes){this.props.onChange({labels:this.props.labels,labelLocation:this.props.labelLocation,range:this.props.range,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,step:this.props.step,gridStep:this.props.gridStep,snapStep:this.props.snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,...changes});}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,buttons:[{value:"onAxis",content:"On Axis"},{value:"alongEdge",content:"Along Graph Edge"}],onChange:labelLocation=>this.handleChange({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,buttons:[{value:"axes",content:"Axes"},{value:"graph",content:"Graph"},{value:"grid",content:"Grid"},{value:"none",content:"None"}],onChange:markings=>this.handleChange({markings}),disabled:editingDisabled})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(Checkbox$1,{label:"Show tooltips",checked:this.props.showTooltips,onChange:showTooltips=>{this.handleChange({showTooltips});},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:showProtractor=>{this.handleChange({showProtractor});},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.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;const showAxisArrows=this.state.showAxisArrowsSwitches;const showAxisTicks=this.state.showAxisTicksSwitches;const step=this.state.stepTextbox;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.handleChange({valid:true,labels:labels,labelLocation:labelLocation,range:range,showAxisArrows:showAxisArrows,showAxisTicks:showAxisTicks,step:step,gridStep:gridStep,snapStep:snapStep,backgroundImage:image});}else {this.handleChange({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}};
1677
1677
 
1678
1678
  var styles$A = {"treeList":"perseus_dM32KBSs","indentList":"perseus_0LO0xYxg","switchRow":"perseus_T8Wphznm"};
1679
1679
 
@@ -1804,7 +1804,7 @@ const StartCoordsSettingsInner=props=>{const{type,range,step,allowReflexAngles,o
1804
1804
 
1805
1805
  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}}
1806
1806
 
1807
- 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)}}
1807
+ const InteractiveGraph=InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React.Component{handleChange(changes){this.props.onChange({step:this.props.step,gridStep:this.props.gridStep,snapStep:this.props.snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,labels:this.props.labels,labelLocation:this.props.labelLocation,showAxisArrows:this.props.showAxisArrows,showAxisTicks:this.props.showAxisTicks,showProtractor:this.props.showProtractor,showRuler:this.props.showRuler,showTooltips:this.props.showTooltips,rulerLabel:this.props.rulerLabel,rulerTicks:this.props.rulerTicks,range:this.props.range,graph:this.props.graph,correct:this.props.correct,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,...changes});}handleSettingsChange({valid,...settings}){this.setState({valid});if(valid===true){this.handleChange(settings);}}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.state.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",options:{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.handleChange({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.state.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.handleChange({graph:{type},correct:{type}});}})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",editingDisabled:this.props.apiOptions?.editingDisabled??false,onChange:options=>this.handleChange(options)}),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:options=>this.handleChange(options)}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:options=>this.handleChange(options)}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:options=>this.handleChange(options)}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:options=>this.handleChange(options)}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:options=>this.handleChange(options)}),!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.state.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:settings=>this.handleSettingsChange(settings),apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:options=>this.handleChange(options),apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.state={valid:true},this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.handleChange({graph:graph});},this.changePointLabels=pointLabels=>{const next=reshapePointLabelsForGraphType(pointLabels,this.props.graph,this.props.correct);if(next){this.handleChange(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.handleChange({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};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)}}
1808
1808
 
1809
1809
  const gray68="#888D93";const gray41="#626569";
1810
1810