@khanacademy/perseus 76.0.2 → 76.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.
package/dist/index.js CHANGED
@@ -24,8 +24,6 @@ var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
24
24
  var ReactDOM = require('react-dom');
25
25
  var wonderBlocksProgressSpinner = require('@khanacademy/wonder-blocks-progress-spinner');
26
26
  var kmath = require('@khanacademy/kmath');
27
- var _class_private_field_loose_base = require('@swc/helpers/_/_class_private_field_loose_base');
28
- var _class_private_field_loose_key = require('@swc/helpers/_/_class_private_field_loose_key');
29
27
  var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
30
28
  var wonderBlocksModal = require('@khanacademy/wonder-blocks-modal');
31
29
  var SimpleMarkdown = require('@khanacademy/simple-markdown');
@@ -1539,12 +1537,26 @@ var constants = /*#__PURE__*/Object.freeze({
1539
1537
  white: white
1540
1538
  });
1541
1539
 
1542
- const MIN_VIEWPORT_HEIGHT=480;class FixedToResponsive extends React__namespace.Component{componentDidMount(){this._isMounted=true;if(window.innerHeight<MIN_VIEWPORT_HEIGHT){setTimeout(this._cacheViewportSize,800);}else {this._cacheViewportSize();}}componentWillUnmount(){this._isMounted=false;}render(){const aspectRatio=this.props.width/this.props.height;let{width,height}=this.props;if(this.props.constrainHeight&&this.state.viewportHeight){const maxHeight=2/3*this.state.viewportHeight;if(this.props.height>=maxHeight){height=maxHeight;width=maxHeight*aspectRatio;}}const style={maxWidth:width,maxHeight:height,aspectRatio:aspectRatio.toFixed(4)};const className=classNames__default.default("fixed-to-responsive",this.props.className);const container=jsxRuntimeExports.jsx("div",{className:className,style:style,children:this.props.children});const shouldFullBleed=this.props.allowFullBleed&&this.state.viewportWidth&&width>=this.state.viewportWidth;if(shouldFullBleed){return jsxRuntimeExports.jsx("div",{style:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin},children:container})}return container}constructor(...args){super(...args),this._isMounted=false,this.state={viewportHeight:null,viewportWidth:null},this._cacheViewportSize=()=>{if(this._isMounted){this.setState({viewportHeight:Math.max(MIN_VIEWPORT_HEIGHT,window.innerHeight),viewportWidth:window.innerWidth});}};}}FixedToResponsive.defaultProps={className:"",constrainHeight:false,allowFullBleed:false};
1540
+ const MIN_VIEWPORT_HEIGHT=480;class FixedToResponsive extends React__namespace.Component{componentDidMount(){this._isMounted=true;if(window.innerHeight<MIN_VIEWPORT_HEIGHT){setTimeout(this._cacheViewportSize,800);}else {this._cacheViewportSize();}}componentWillUnmount(){this._isMounted=false;}render(){const aspectRatio=this.props.width/this.props.height;let{width,height}=this.props;if(this.props.constrainHeight&&this.state.viewportHeight){const maxHeight=2/3*this.state.viewportHeight;if(this.props.height>=maxHeight){height=maxHeight;width=maxHeight*aspectRatio;}}const style={maxWidth:width,maxHeight:height,aspectRatio:aspectRatio.toFixed(4)};const className=classNames__default.default("fixed-to-responsive",this.props.className);const container=jsxRuntimeExports.jsx("div",{className:className,style:style,"data-scale":this.props.scale,children:this.props.children});const shouldFullBleed=this.props.allowFullBleed&&this.state.viewportWidth&&width>=this.state.viewportWidth;if(shouldFullBleed){return jsxRuntimeExports.jsx("div",{style:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin},children:container})}return container}constructor(...args){super(...args),this._isMounted=false,this.state={viewportHeight:null,viewportWidth:null},this._cacheViewportSize=()=>{if(this._isMounted){this.setState({viewportHeight:Math.max(MIN_VIEWPORT_HEIGHT,window.innerHeight),viewportWidth:window.innerWidth});}};}}FixedToResponsive.defaultProps={className:"",constrainHeight:false,allowFullBleed:false};
1543
1541
 
1544
1542
  function getKey$2(eventName,id){return eventName+":"+id}function getEventName$2(key){return key.split(":")[0]}const MovableHelperMethods={_fireEvent:function(listeners,...args){for(const listener of listeners){listener.call(this,...args);}},_applyConstraints:function(current,previous,extraOptions){let skipRemaining=false;return ___default.default.reduce(this.state.constraints,(memo,constraint)=>{if(memo===false){return false}if(skipRemaining){return memo}const result=constraint.call(this,memo,previous,{onSkipRemaining:()=>{skipRemaining=true;},...extraOptions});if(result===false){return false}if(kmath.point.is(result,2)){return result}if(result===true||result==null){return memo}throw new perseusCore.PerseusError("Constraint returned invalid result: "+result,perseusCore.Errors.Internal)},current,this)},draw:function(){const currState=this.cloneState();MovableHelperMethods._fireEvent.call(this,this.state.draw,currState,this.prevState);this.prevState=currState;},listen:function(eventName,id,func){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key]=this._listenerMap[key]||this.state[eventName].length;this.state[eventName][index]=func;},unlisten:function(eventName,id){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key];if(index!==undefined){this.state[eventName].splice(index,1);delete this._listenerMap[key];const keys=___default.default.keys(this._listenerMap);___default.default.each(keys,function(key){if(getEventName$2(key)===eventName&&this._listenerMap[key]>index){this._listenerMap[key]--;}},this);}}};
1545
1543
 
1546
1544
  let prefixedTransform=null;function computePrefixedTransform(){const el=document.createElement("div");const prefixes=["transform","msTransform","MozTransform","WebkitTransform","OTransform"];let correctPrefix=null;___default.default.each(prefixes,function(prefix){if(typeof el.style[prefix]!=="undefined"){correctPrefix=prefix;}});return correctPrefix}let canUse3dTransform=null;function computeCanUse3dTransform(){const el=document.createElement("div");const prefix=InteractiveUtil.getPrefixedTransform();el.style[prefix]="translateZ(0px)";return !!el.style[prefix]}const FUNCTION_ARRAY_OPTIONS=["add","modify","draw","remove","constraints","onMoveStart","onMove","onMoveEnd","onClick"];const InteractiveUtil={assert:function(isTrue,message){if(!isTrue){throw new perseusCore.PerseusError("Assertion Error"+(message?": "+message:""),perseusCore.Errors.Internal)}},createGettersFor:function(Class,defaults){___default.default.each(___default.default.keys(defaults),function(key){if(Class.prototype[key]===undefined){Class.prototype[key]=function(){return this.state[key]};}});},addMovableHelperMethodsTo:function(Class){___default.default.each(MovableHelperMethods,function(methodFunc,methodName){if(Class.prototype[methodName]===undefined){Class.prototype[methodName]=methodFunc;}});},arrayify:function(funcOrArray){if(funcOrArray==null){return []}if(___default.default.isArray(funcOrArray)){return ___default.default.filter(___default.default.flatten(funcOrArray),___default.default.identity)}return [funcOrArray]},normalizeOptions:function(options){const result={...options};FUNCTION_ARRAY_OPTIONS.forEach(function(eventName){if(options[eventName]!==undefined){result[eventName]=InteractiveUtil.arrayify(options[eventName]);}});return result},getPrefixedTransform:function(){prefixedTransform=prefixedTransform||computePrefixedTransform();return prefixedTransform},getCanUse3dTransform:function(){if(canUse3dTransform==null){canUse3dTransform=computeCanUse3dTransform();}return canUse3dTransform}};
1547
1545
 
1546
+ function _class_private_field_loose_base(receiver, privateKey) {
1547
+ if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
1548
+ throw new TypeError("attempted to use private field on non-instance");
1549
+ }
1550
+
1551
+ return receiver;
1552
+ }
1553
+
1554
+ var id = 0;
1555
+
1556
+ function _class_private_field_loose_key(name) {
1557
+ return "__private_" + id++ + "_" + name;
1558
+ }
1559
+
1548
1560
  /*!
1549
1561
  * Raphael 1.5.2 - JavaScript Vector Library
1550
1562
  *
@@ -1598,7 +1610,7 @@ const reactRootCache=new WeakMap;function render(element,container){const childr
1598
1610
 
1599
1611
  function findChildOrAdd(elem,className){const $child=$__default.default(elem).find("."+className);if($child.length===0){return $__default.default("<span>").addClass(className).appendTo($__default.default(elem))}return $child}var Tex$1 = {processMath:async function(elem,text,force,callback){const $elem=$__default.default(elem);if($elem.attr("data-math-formula")==null||force){const $texHolder=findChildOrAdd($elem,"tex-holder");if(text==null&&$elem.attr("data-math-formula")){text=$elem.attr("data-math-formula");}text=text!=null?text+"":"";text=kmath.KhanMath.cleanMath(text);$elem.attr("data-math-formula",text);const{TeX}=await getDependencies();render(React__namespace.createElement(TeX,{children:text,onRender:callback}),$texHolder[0]);}}};
1600
1612
 
1601
- const{processMath: processMath$1}=Tex$1;function polar$2(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}var _bounds=/*#__PURE__*/_class_private_field_loose_key._("_bounds"),_drawingTransform=/*#__PURE__*/_class_private_field_loose_key._("_drawingTransform");let Graphie$1 = class Graphie{init(options){let scale=options.scale||[40,40];scale=typeof scale==="number"?[scale,scale]:scale;if(options.range==null){throw new perseusCore.PerseusError("range should be specified in graph init",perseusCore.Errors.Internal)}_class_private_field_loose_base._(this,_bounds)[_bounds]=new GraphBounds(...options.range);_class_private_field_loose_base._(this,_drawingTransform)[_drawingTransform]=new DrawingTransform(this.raphael,scale,this.bounds());const[w,h]=this.drawingTransform().canvasDimensions();$__default.default(this.el).css({width:w,height:h});this.range=options.range;this.scale=scale;this.dimensions=[w,h];this.xpixels=w;this.ypixels=h;this.isMobile=options.isMobile??false;return this}graphInit(options){options=options||{};for(const[prop,val]of wonderStuffCore.entries(options)){if(!prop.match(/.*Opacity$/)&&prop!=="range"&&typeof val==="number"){options[prop]=[val,val];}if(prop==="range"||prop==="gridRange"){options[prop]=normalizeRange(options[prop]);}}const range=normalizeRange(options.range||[[-10,10],[-10,10]]);const gridRange=normalizeRange(options.gridRange||range);const scale=options.scale||[20,20];const grid=options.grid!=null?options.grid:true;const gridOpacity=options.gridOpacity||.1;const gridStep=toPair(options.gridStep||[1,1]);const axes=options.axes!=null?options.axes:true;const axisArrows=options.axisArrows||"";const axisOpacity=options.axisOpacity||1;const axisCenter=options.axisCenter||[Math.min(Math.max(range[0][0],0),range[0][1]),Math.min(Math.max(range[1][0],0),range[1][1])];const axisLabels=options.axisLabels!=null?options.axisLabels:false;const ticks=options.ticks!=null?options.ticks:true;const tickStep=options.tickStep||[2,2];const tickLen=options.tickLen||[5,5];const tickOpacity=options.tickOpacity||1;const labels=options.labels||options.labelStep||false;const labelStep=options.labelStep||[1,1];const labelOpacity=options.labelOpacity||1;let unityLabels=options.unityLabels||false;const labelFormat=options.labelFormat||function(a){return a};let xLabelFormat=options.xLabelFormat||labelFormat;let yLabelFormat=options.yLabelFormat||labelFormat;const realRange=[[range[0][0]-(range[0][0]>0?1:0),range[0][1]+(range[0][1]<0?1:0)],[range[1][0]-(range[1][0]>0?1:0),range[1][1]+(range[1][1]<0?1:0)]];if(!Array.isArray(unityLabels)){unityLabels=[unityLabels,unityLabels];}const minusIgnorer=function(lf){return function(a){return (lf(a)+"").replace(/-(\d)/g,"\\llap{-}$1")}};xLabelFormat=minusIgnorer(xLabelFormat);yLabelFormat=minusIgnorer(yLabelFormat);this.init({range:realRange,scale:scale,isMobile:options.isMobile});if(grid){this.grid(gridRange[0],gridRange[1],{stroke:options.isMobile?KhanColors.GRAY_C:"#000000",opacity:options.isMobile?1:gridOpacity,step:gridStep,strokeWidth:options.isMobile?1:2});}if(axes){if(axisArrows==="<->"||axisArrows===true){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:axisOpacity,strokeWidth:options.isMobile?1:2,arrows:"->"},function(){if(range[1][0]<0&&range[1][1]>0){thisGraphie.path([axisCenter,[gridRange[0][0],axisCenter[1]]]);thisGraphie.path([axisCenter,[gridRange[0][1],axisCenter[1]]]);}if(range[0][0]<0&&range[0][1]>0){thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][0]]]);thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][1]]]);}});}else if(axisArrows==="->"||axisArrows===""){const thisGraphie=this;this.style({stroke:"#000000",opacity:axisOpacity,strokeWidth:2,arrows:axisArrows},function(){thisGraphie.path([[gridRange[0][0],axisCenter[1]],[gridRange[0][1],axisCenter[1]]]);thisGraphie.path([[axisCenter[0],gridRange[1][0]],[axisCenter[0],gridRange[1][1]]]);});}if(axisLabels&&axisLabels.length===2){this.label([gridRange[0][1],axisCenter[1]],axisLabels[0],"right");this.label([axisCenter[0],gridRange[1][1]],axisLabels[1],"above");}}if(ticks){const halfWidthTicks=options.isMobile;const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:tickOpacity,strokeWidth:1},()=>{let step=gridStep[0]*tickStep[0];let len=tickLen[0]/scale[1];let start=gridRange[0][0];let stop=gridRange[0][1];if(range[1][0]<0&&range[1][1]>0){for(let x=step+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}for(let x=-step+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}}step=gridStep[1]*tickStep[1];len=tickLen[1]/scale[0];start=gridRange[1][0];stop=gridRange[1][1];if(range[0][0]<0&&range[0][1]>0){for(let y=step+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}for(let y=-step+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}}});}if(labels){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:labelOpacity},function(){let step=gridStep[0]*tickStep[0]*labelStep[0];let start=gridRange[0][0];let stop=gridRange[0][1];const xAxisPosition=axisCenter[0]<0?"above":"below";const yAxisPosition=axisCenter[0]<0?"right":"left";const xShowZero=axisCenter[0]===0&&axisCenter[1]!==0;const yShowZero=axisCenter[0]!==0&&axisCenter[1]===0;const axisOffCenter=axisCenter[0]!==0||axisCenter[1]!==0;const showUnityX=unityLabels[0]||axisOffCenter;const showUnityY=unityLabels[1]||axisOffCenter;for(let x=(xShowZero?0:step)+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}for(let x=-step*(showUnityX?1:2)+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}step=gridStep[1]*tickStep[1]*labelStep[1];start=gridRange[1][0];stop=gridRange[1][1];for(let y=(yShowZero?0:step)+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}for(let y=-step*(showUnityY?1:2)+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}});}}drawingTransform(){if(_class_private_field_loose_base._(this,_drawingTransform)[_drawingTransform]==null){throw new Error("Can't get drawingTransform of an uninitialized Graphie")}return _class_private_field_loose_base._(this,_drawingTransform)[_drawingTransform]}bounds(){if(_class_private_field_loose_base._(this,_bounds)[_bounds]==null){throw new Error("Can't get bounds of an uninitialized Graphie")}return _class_private_field_loose_base._(this,_bounds)[_bounds]}style(attrs,fn){const processed=this.processAttributes(attrs);if(typeof fn==="function"){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...processed};const result=fn.call(this);this.currentStyle=oldStyle;return result}Object.assign(this.currentStyle,processed);}grid(xr,yr,style){return this.withStyle(style,()=>{const step=this.currentStyle.step||[1,1];const set=this.raphael.set();let x=step[0]*Math.ceil(xr[0]/step[0]);for(;x<=xr[1];x+=step[0]){set.push(this.line([x,yr[0]],[x,yr[1]]));}let y=step[1]*Math.ceil(yr[0]/step[1]);for(;y<=yr[1];y+=step[1]){set.push(this.line([xr[0],y],[xr[1],y]));}return set})}arc(center,radius,startAngle,endAngle,sector,style){return this.withStyle(style,()=>{startAngle=(startAngle%360+360)%360;endAngle=(endAngle%360+360)%360;const cent=this.scalePoint(center);const radii=this.scaleVector(radius);const startVector=polar$2(radius,startAngle);const endVector=polar$2(radius,endAngle);const round=x=>kmath.number.round(x,6);const startPoint=this.scalePoint([round(center[0]+startVector[0]),round(center[1]+startVector[1])]);const endPoint=this.scalePoint([round(center[0]+endVector[0]),round(center[1]+endVector[1])]);const largeAngle=((endAngle-startAngle)%360+360)%360>180;return this.raphael.path("M"+startPoint.join(" ")+"A"+radii.join(" ")+" 0 "+(largeAngle?1:0)+" 0 "+endPoint.join(" ")+(sector?"L"+cent.join(" ")+"z":""))})}circle(center,radius,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center),...this.scaleVector([radius,radius])))}rect(x,y,width,height,style){return this.withStyle(style,()=>{const corner=this.scalePoint([x,y+height]);const dims=this.scaleVector([width,height]);const elem=this.raphael.rect(...corner.concat(dims));if(this.isMobile){elem.node.style.shapeRendering="crispEdges";}return elem})}ellipse(center,radii,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center).concat(this.scaleVector(radii))))}fixedEllipse(center,radii,maxScale,padding,style){return this.withStyle(style,()=>{const scaledPoint=this.scalePoint(center);const scaledRadii=this.scaleVector(radii);const width=2*scaledRadii[0]*maxScale+padding;const height=2*scaledRadii[1]*maxScale+padding;const left=scaledPoint[0]-width/2;const top=scaledPoint[1]-height/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px"});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.ellipse(width/2,height/2,scaledRadii[0],scaledRadii[1]);return {wrapper:wrapper,visibleShape:visibleShape}})}unstyledPath(points){const p=this.raphael.path(this.svgPath(points));p.graphiePath=points;return p}path(points,style){return this.withStyle(style,()=>{return this.unstyledPath(points)})}fixedPath(points,center,createPath){points=points.map(this.scalePoint);center=center?this.scalePoint(center):null;createPath=createPath||this.svgPath;const xs=points.map(p=>p[0]);const ys=points.map(p=>p[1]);const pathLeft=Math.min(...xs);const pathRight=Math.max(...xs);const pathTop=Math.min(...ys);const pathBottom=Math.max(...ys);const padding=[4,4];const topLeftOfBoundingBox=[pathLeft,pathTop];points=points.map(function(point){return kmath.vector.add(kmath.vector.subtract(point,topLeftOfBoundingBox),kmath.vector.scale(padding,.5))});const width=pathRight-pathLeft+padding[0];const height=pathBottom-pathTop+padding[1];const left=topLeftOfBoundingBox[0]-padding[0]/2;const top=topLeftOfBoundingBox[1]-padding[1]/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:center?width/2+center[0]+"px "+(height/2+center[1])+"px":null});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.path(createPath(points));return {wrapper:wrapper,visibleShape:visibleShape}}scaledPath(points,style){return this.withStyle(style,()=>{const p=this.raphael.path(this.svgPath(points,true));p.graphiePath=points;return p})}line(start,end,style){return this.withStyle(style,()=>{const l=this.unstyledPath([start,end]);if(this.isMobile){l.node.style.shapeRendering="crispEdges";}return l})}parabola(a,b,c,style){return this.withStyle(style,()=>this.raphael.path(this.svgParabolaPath(a,b,c)))}fixedLine(start,end,thickness){const padding=[thickness,thickness];start=this.scalePoint(start);end=this.scalePoint(end);const extraOffset=[Math.min(start[0],end[0]),Math.min(start[1],end[1])];start=kmath.vector.add(kmath.vector.subtract(start,extraOffset),kmath.vector.scale(padding,.5));end=kmath.vector.add(kmath.vector.subtract(end,extraOffset),kmath.vector.scale(padding,.5));const left=extraOffset[0]-padding[0]/2;const top=extraOffset[1]-padding[1]/2;const width=Math.abs(start[0]-end[0])+padding[0];const height=Math.abs(start[1]-end[1])+padding[1];const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:start[0]+"px "+start[1]+"px"});const localRaphael=Raphael$1(wrapper,width,height);const path="M"+start[0]+" "+start[1]+" "+"L"+end[0]+" "+end[1];const visibleShape=localRaphael.path(path);visibleShape.graphiePath=[start,end];return {wrapper:wrapper,visibleShape:visibleShape}}sinusoid(a,b,c,d,style){return this.withStyle(style,()=>this.raphael.path(this.svgSinusoidPath(a,b,c,d)))}plotParametric(fn,range,style){return this.withStyle(style,()=>{const clip=xy=>{if(Math.abs(xy[1])>5e5){return [xy[0],Math.min(Math.max(xy[1],-5e5),5e5)]}return xy};const clippedFn=x=>clip(fn(x));const min=range[0];const max=range[1];let step=(max-min)/(this.currentStyle["plot-points"]||800);if(step===0){step=1;}const paths=this.raphael.set();let points=[];let lastY=clippedFn(min)[1];for(let t=min;t<=max;t+=step){const point=clippedFn(t);const y=point[1];if(y>0!==lastY>0&&Math.abs(y-lastY)>2*this.drawingTransform().pixelsPerUnitY()||isNaN(y)){paths.push(this.unstyledPath(points));points=[];}else {points.push(point);}lastY=y;}paths.push(this.unstyledPath(points));return paths})}plot(fn,range,style){return this.withStyle(style,()=>{const min=range[0];const max=range[1];if(!this.currentStyle["plot-points"]){this.currentStyle["plot-points"]=2*(max-min)*this.drawingTransform().pixelsPerUnitX();}const parametricFn=x=>[x,fn(x)];return this.plotParametric(parametricFn,range)})}withStyle(style,fn){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...this.processAttributes(style)};const result=this.postprocessDrawingResult(fn());this.currentStyle=oldStyle;return result}postprocessDrawingResult(result){const type=result.constructor.prototype;if(type===Raphael$1.el||type===Raphael$1.st){result.attr(this.currentStyle);if(this.currentStyle.arrows){result=this.addArrowheads(result);}}else if(result instanceof $__default.default){result.css({...this.currentStyle,...SVG_SPECIFIC_STYLE_MASK});}return result}addArrowheads(path){const type=path.constructor.prototype;if(type===Raphael$1.el){if(path.type==="path"&&typeof path.arrowheadsDrawn==="undefined"){const w=path.attr("stroke-width");const s=.6+.4*w;const l=path.getTotalLength();const set=this.raphael.set();const head=this.raphael.path(this.isMobile?"M-4,4 C-4,4 -0.25,0 -0.25,0 C-0.25,0 -4,-4 -4,-4":"M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4");const end=path.getPointAtLength(l-.4);const almostTheEnd=path.getPointAtLength(l-.75*s);const angle=Math.atan2(end.y-almostTheEnd.y,end.x-almostTheEnd.x)*180/Math.PI;const attrs=path.attr();delete attrs.path;let subpath=path.getSubpath(0,l-.75*s);subpath=this.raphael.path(subpath).attr(attrs);subpath.arrowheadsDrawn=true;path.remove();head.rotate(angle,this.isMobile?1e-5:.75,0).scale(s,s,.75,0).translate(almostTheEnd.x,almostTheEnd.y).attr(attrs).attr({"stroke-linejoin":"round","stroke-linecap":"round"});head.arrowheadsDrawn=true;set.push(subpath);set.push(head);return set}}else if(type===Raphael$1.st){for(let i=0,l=path.items.length;i<l;i++){this.addArrowheads(path.items[i]);}}return path}processAttributes(attrs){const transformers={scale:scale=>{this.drawingTransform().setScale(scale);},clipRect:pair=>{const point=pair[0];const size=pair[1];point[1]+=size[1];return {"clip-rect":this.scalePoint(point).concat(this.scaleVector(size)).join(" ")}},strokeWidth:function(val){return {"stroke-width":parseFloat(val)}},rx:val=>{return {rx:this.scaleVector([val,0])[0]}},ry:val=>{return {ry:this.scaleVector([0,val])[1]}},r:val=>{const scaled=this.scaleVector([val,val]);return {rx:scaled[0],ry:scaled[1]}}};const processed={};Object.entries(attrs||{}).forEach(function([key,value]){const transformer=transformers[key];if(typeof transformer==="function"){Object.assign(processed,transformer(value));}else {const dasherized=String(key).replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();processed[dasherized]=value;}});return processed}addMouseLayer(options){const localOptions={allowScratchpad:false,setDrawingAreaAvailable:function(){},...options};const mouselayerZIndex=2;this.mouselayer=Raphael$1(this.el,this.xpixels,this.ypixels);$__default.default(this.mouselayer.canvas).css("z-index",mouselayerZIndex);if(localOptions.onClick||localOptions.onMouseDown||localOptions.onMouseMove||localOptions.onMouseOver||localOptions.onMouseOut){const canvasClickTarget=this.mouselayer.rect(0,0,this.xpixels,this.ypixels).attr({fill:"#000",opacity:0});let isClickingCanvas=false;$__default.default(this.mouselayer.canvas).on("vmousedown",e=>{if(e.target===canvasClickTarget[0]){if(localOptions.onMouseDown){localOptions.onMouseDown(this.getMouseCoord(e));}isClickingCanvas=true;if(localOptions.onMouseMove){const handler=localOptions.onMouseMove;$__default.default(document).bind("vmousemove.mouseLayer",e=>{if(isClickingCanvas){e.preventDefault();handler(this.getMouseCoord(e));}});}$__default.default(document).bind("vmouseup.mouseLayer",e=>{$__default.default(document).unbind(".mouseLayer");if(isClickingCanvas&&localOptions.onClick){localOptions.onClick(this.getMouseCoord(e));}isClickingCanvas=false;});}});if(localOptions.onMouseOver){const handler=localOptions.onMouseOver;$__default.default(this.mouselayer.canvas).on("vmouseover",e=>{handler(this.getMouseCoord(e));});}if(localOptions.onMouseOut){const handler=localOptions.onMouseOut;$__default.default(this.mouselayer.canvas).on("vmouseout",e=>{handler(this.getMouseCoord(e));});}}if(!localOptions.allowScratchpad){localOptions.setDrawingAreaAvailable?.(false);}this._mouselayerWrapper=document.createElement("div");$__default.default(this._mouselayerWrapper).css({position:"absolute",left:0,top:0,zIndex:mouselayerZIndex});this._visiblelayerWrapper=document.createElement("div");$__default.default(this._visiblelayerWrapper).css({position:"absolute",left:0,top:0});const el=this.el;el.appendChild(this._visiblelayerWrapper);el.appendChild(this._mouselayerWrapper);this.addToMouseLayerWrapper=el=>{this._mouselayerWrapper?.appendChild(el);};this.addToVisibleLayerWrapper=el=>{this._visiblelayerWrapper?.appendChild(el);};}addToMouseLayerWrapper(el){throw new Error("addToMouseLayerWrapper is not ready. Call addMouseLayer() first.")}addToVisibleLayerWrapper(el){throw new Error("addToVisibleLayerWrapper is not ready. Call addMouseLayer() first.")}getMousePx(event){const offset=$__default.default(this.el).offset();const mouseX=event.pageX-offset.left;const mouseY=event.pageY-offset.top;return [mouseX,mouseY]}getMouseCoord(event){return this.unscalePoint(this.getMousePx(event))}constructor(el){Object.defineProperty(this,_bounds,{writable:true,value:void 0});Object.defineProperty(this,_drawingTransform,{writable:true,value:void 0});this.isMobile=false;this.currentStyle={"stroke-width":2,fill:"none"};this.label=(point,text,direction,arg4,arg5)=>{const style=typeof arg4==="object"?arg4:arg5;const latex=typeof arg4==="boolean"?arg4:true;return this.withStyle(style,()=>{const $span=$__default.default("<span>").addClass("graphie-label");const pad=this.currentStyle["label-distance"];$span.css({position:"absolute",padding:(pad!=null?pad:7)+"px",color:"black"}).data("labelDirection",direction).appendTo(this.el);$span.setPosition=point=>{const scaledPoint=this.scalePoint(point);$span.css({left:scaledPoint[0],top:scaledPoint[1]});};$span.setPosition(point);const span=$span[0];$span.processMath=function(math,force){processMath$1(span,math,force,function(){const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);});};$span.processText=function(text){$span.html(text);const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);};if(latex){$span.processMath(text,false);}else {$span.processText(text);}return $span})};this.svgPath=(points,alreadyScaled)=>{return points.map((point,i)=>{if(point===true){return "z"}const scaled=alreadyScaled?point:this.scalePoint(point);return (i===0?"M":"L")+kmath.KhanMath.bound(scaled[0])+" "+kmath.KhanMath.bound(scaled[1])}).join("")};this.svgParabolaPath=(a,b,c)=>{const computeParabola=function(x){return (a*x+b)*x+c};if(a===0){const points=[[this.bounds().xMin,computeParabola(this.bounds().xMin)],[this.bounds().xMax,computeParabola(this.bounds().xMax)]];return this.svgPath(points)}const xVertex=-b/(2*a);const distToEdge=Math.max(Math.abs(xVertex-this.bounds().xMin),Math.abs(xVertex-this.bounds().xMax));const xPoint=xVertex+distToEdge;const vertex=[xVertex,computeParabola(xVertex)];const point=[xPoint,computeParabola(xPoint)];const control=[vertex[0],vertex[1]-(point[1]-vertex[1])];const dx=Math.abs(vertex[0]-point[0]);const left=[vertex[0]-dx,point[1]];const right=[vertex[0]+dx,point[1]];const points=[left,control,right].map(this.scalePoint);const values=points.flat().map(kmath.KhanMath.bound);return "M"+values[0]+","+values[1]+" Q"+values[2]+","+values[3]+" "+values[4]+","+values[5]};this.svgSinusoidPath=(a,b,c,d)=>{const quarterPeriod=Math.abs(Math.PI/(2*b));const computeSine=function(x){return a*Math.sin(b*x-c)+d};const computeDerivative=function(x){return a*b*Math.cos(c-b*x)};const coordsForOffset=(initial,i)=>{const x0=initial+quarterPeriod*i;const x1=x0+quarterPeriod;const xCoords=[x0,x0*2/3+x1*1/3,x0*1/3+x1*2/3,x1];const yCoords=[computeSine(x0),computeSine(x0)+computeDerivative(x0)*(x1-x0)/3,computeSine(x1)-computeDerivative(x1)*(x1-x0)/3,computeSine(x1)];const points=kmath.vector.zip(xCoords,yCoords);return points.map(this.scalePoint)};const extent=this.bounds().width();const numQuarterPeriods=Math.ceil(extent/quarterPeriod)+1;let initial=c/b;const distToEdge=initial-this.bounds().xMin;initial-=quarterPeriod*Math.ceil(distToEdge/quarterPeriod);let coords=coordsForOffset(initial,0);let path="M"+coords[0][0]+","+coords[0][1]+" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];for(let i=1;i<numQuarterPeriods;i++){coords=coordsForOffset(initial,i);path+=" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];}return path};this.scalePoint=point=>{return this.drawingTransform().scalePoint(point)};this.scaleVector=point=>{return this.drawingTransform().scaleVector(point)};this.unscalePoint=point=>{return this.drawingTransform().unscalePoint(point)};this.unscaleVector=point=>{return this.drawingTransform().unscaleVector(point)};this.el=el;$__default.default(el).css("position","relative");this.raphael=Raphael$1(el);$__default.default(el).attr("aria-hidden","true");$__default.default(el).children("div").css("position","absolute");}};const labelDirections={center:[-0.5,-0.5],above:[-0.5,-1],"above right":[0,-1],right:[0,-0.5],"below right":[0,0],below:[-0.5,0],"below left":[-1,0],left:[-1,-0.5],"above left":[-1,-1]};function normalizeRange(range){function normalizeInterval(magnitude){if(typeof magnitude==="number"){return [-magnitude,magnitude]}else {return magnitude}}function getXAndYRanges(range){if(Array.isArray(range)){return range}else {return [range,range]}}if(range==null){return range}const[xRange,yRange]=getXAndYRanges(range);return [normalizeInterval(xRange),normalizeInterval(yRange)]}function toPair(x){if(Array.isArray(x)){return x}return [x,x]}const SVG_SPECIFIC_STYLE_MASK={"stroke-width":null};const setLabelMargins=function(span,size){const $span=$__default.default(span);const direction=$span.data("labelDirection");let[width,height]=size;if(width===0&&height===0){[width,height]=[1,1];Log.log("Label size was 0x0 in graphie.js; using 1x1 instead");}$span.css("visibility","");if(typeof direction==="number"){const x=Math.cos(direction);const y=Math.sin(direction);const scale=Math.min(width/2/Math.abs(x),height/2/Math.abs(y));$span.css({marginLeft:-width/2+x*scale,marginTop:-height/2-y*scale});}else {const currentHeightMatchesProps=span.scrollHeight===height;const $svgImage=$span.closest(".svg-image");const $graphie=$span.closest(".graphie");const $container=$svgImage.length>0?$svgImage:$graphie;$container.css("line-height","normal");if(currentHeightMatchesProps&&span.scrollHeight!==height){height=span.scrollHeight;}const widthValues=$container.css(["max-width","width"])??{"max-width":"0px"};const expectedWidth=widthValues["max-width"]!=="none"?widthValues["max-width"]:widthValues["width"];let scale=($container.width()??0)/parseInt(expectedWidth.replace(/px$/,""))*100;if(isNaN(scale)){scale=100;}else if(scale===0){scale=100;}const padding=$span.css("padding")??"0px";const currentPadding=padding!=="none"?padding:"0px";const newPadding=Math.round(parseInt(currentPadding.replace(/px$/,""))*scale)/100;const multipliers=labelDirections[direction||"center"];const styling={marginLeft:Math.round(width*multipliers[0]*scale)/100,marginTop:Math.round(height*multipliers[1]*scale)/100,padding:`${newPadding}px`};if(scale!==1){styling["fontSize"]=`${Math.round(scale*100)/100}%`;}$span.css(styling);}};const GraphUtils={Graphie: Graphie$1,createGraphie:function(el){return new Graphie$1(el)},unscaledSvgPath:function(points){if(points[0]===true){return ""}return points.map(function(point,i){if(point===true){return "z"}return (i===0?"M":"L")+point[0]+" "+point[1]}).join("")},getDistance:function(point1,point2){return kmath.point.distanceToPoint(point1,point2)},findAngleDeprecated:function(point1,point2,vertex){if(vertex===undefined){const x=point1[0]-point2[0];const y=point1[1]-point2[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360}return GraphUtils.findAngleDeprecated(point1,vertex)-GraphUtils.findAngleDeprecated(point2,vertex)},graphs:{}};
1613
+ const{processMath: processMath$1}=Tex$1;function polar$2(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}var _bounds=/*#__PURE__*/_class_private_field_loose_key("_bounds"),_drawingTransform=/*#__PURE__*/_class_private_field_loose_key("_drawingTransform");let Graphie$1 = class Graphie{init(options){let scale=options.scale||[40,40];scale=typeof scale==="number"?[scale,scale]:scale;if(options.range==null){throw new perseusCore.PerseusError("range should be specified in graph init",perseusCore.Errors.Internal)}_class_private_field_loose_base(this,_bounds)[_bounds]=new GraphBounds(...options.range);_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]=new DrawingTransform(this.raphael,scale,this.bounds());const[w,h]=this.drawingTransform().canvasDimensions();$__default.default(this.el).css({width:w,height:h});this.range=options.range;this.scale=scale;this.dimensions=[w,h];this.xpixels=w;this.ypixels=h;this.isMobile=options.isMobile??false;return this}graphInit(options){options=options||{};for(const[prop,val]of wonderStuffCore.entries(options)){if(!prop.match(/.*Opacity$/)&&prop!=="range"&&typeof val==="number"){options[prop]=[val,val];}if(prop==="range"||prop==="gridRange"){options[prop]=normalizeRange(options[prop]);}}const range=normalizeRange(options.range||[[-10,10],[-10,10]]);const gridRange=normalizeRange(options.gridRange||range);const scale=options.scale||[20,20];const grid=options.grid!=null?options.grid:true;const gridOpacity=options.gridOpacity||.1;const gridStep=toPair(options.gridStep||[1,1]);const axes=options.axes!=null?options.axes:true;const axisArrows=options.axisArrows||"";const axisOpacity=options.axisOpacity||1;const axisCenter=options.axisCenter||[Math.min(Math.max(range[0][0],0),range[0][1]),Math.min(Math.max(range[1][0],0),range[1][1])];const axisLabels=options.axisLabels!=null?options.axisLabels:false;const ticks=options.ticks!=null?options.ticks:true;const tickStep=options.tickStep||[2,2];const tickLen=options.tickLen||[5,5];const tickOpacity=options.tickOpacity||1;const labels=options.labels||options.labelStep||false;const labelStep=options.labelStep||[1,1];const labelOpacity=options.labelOpacity||1;let unityLabels=options.unityLabels||false;const labelFormat=options.labelFormat||function(a){return a};let xLabelFormat=options.xLabelFormat||labelFormat;let yLabelFormat=options.yLabelFormat||labelFormat;const realRange=[[range[0][0]-(range[0][0]>0?1:0),range[0][1]+(range[0][1]<0?1:0)],[range[1][0]-(range[1][0]>0?1:0),range[1][1]+(range[1][1]<0?1:0)]];if(!Array.isArray(unityLabels)){unityLabels=[unityLabels,unityLabels];}const minusIgnorer=function(lf){return function(a){return (lf(a)+"").replace(/-(\d)/g,"\\llap{-}$1")}};xLabelFormat=minusIgnorer(xLabelFormat);yLabelFormat=minusIgnorer(yLabelFormat);this.init({range:realRange,scale:scale,isMobile:options.isMobile});if(grid){this.grid(gridRange[0],gridRange[1],{stroke:options.isMobile?KhanColors.GRAY_C:"#000000",opacity:options.isMobile?1:gridOpacity,step:gridStep,strokeWidth:options.isMobile?1:2});}if(axes){if(axisArrows==="<->"||axisArrows===true){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:axisOpacity,strokeWidth:options.isMobile?1:2,arrows:"->"},function(){if(range[1][0]<0&&range[1][1]>0){thisGraphie.path([axisCenter,[gridRange[0][0],axisCenter[1]]]);thisGraphie.path([axisCenter,[gridRange[0][1],axisCenter[1]]]);}if(range[0][0]<0&&range[0][1]>0){thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][0]]]);thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][1]]]);}});}else if(axisArrows==="->"||axisArrows===""){const thisGraphie=this;this.style({stroke:"#000000",opacity:axisOpacity,strokeWidth:2,arrows:axisArrows},function(){thisGraphie.path([[gridRange[0][0],axisCenter[1]],[gridRange[0][1],axisCenter[1]]]);thisGraphie.path([[axisCenter[0],gridRange[1][0]],[axisCenter[0],gridRange[1][1]]]);});}if(axisLabels&&axisLabels.length===2){this.label([gridRange[0][1],axisCenter[1]],axisLabels[0],"right");this.label([axisCenter[0],gridRange[1][1]],axisLabels[1],"above");}}if(ticks){const halfWidthTicks=options.isMobile;const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:tickOpacity,strokeWidth:1},()=>{let step=gridStep[0]*tickStep[0];let len=tickLen[0]/scale[1];let start=gridRange[0][0];let stop=gridRange[0][1];if(range[1][0]<0&&range[1][1]>0){for(let x=step+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}for(let x=-step+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}}step=gridStep[1]*tickStep[1];len=tickLen[1]/scale[0];start=gridRange[1][0];stop=gridRange[1][1];if(range[0][0]<0&&range[0][1]>0){for(let y=step+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}for(let y=-step+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}}});}if(labels){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:labelOpacity},function(){let step=gridStep[0]*tickStep[0]*labelStep[0];let start=gridRange[0][0];let stop=gridRange[0][1];const xAxisPosition=axisCenter[0]<0?"above":"below";const yAxisPosition=axisCenter[0]<0?"right":"left";const xShowZero=axisCenter[0]===0&&axisCenter[1]!==0;const yShowZero=axisCenter[0]!==0&&axisCenter[1]===0;const axisOffCenter=axisCenter[0]!==0||axisCenter[1]!==0;const showUnityX=unityLabels[0]||axisOffCenter;const showUnityY=unityLabels[1]||axisOffCenter;for(let x=(xShowZero?0:step)+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}for(let x=-step*(showUnityX?1:2)+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}step=gridStep[1]*tickStep[1]*labelStep[1];start=gridRange[1][0];stop=gridRange[1][1];for(let y=(yShowZero?0:step)+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}for(let y=-step*(showUnityY?1:2)+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}});}}drawingTransform(){if(_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]==null){throw new Error("Can't get drawingTransform of an uninitialized Graphie")}return _class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]}bounds(){if(_class_private_field_loose_base(this,_bounds)[_bounds]==null){throw new Error("Can't get bounds of an uninitialized Graphie")}return _class_private_field_loose_base(this,_bounds)[_bounds]}style(attrs,fn){const processed=this.processAttributes(attrs);if(typeof fn==="function"){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...processed};const result=fn.call(this);this.currentStyle=oldStyle;return result}Object.assign(this.currentStyle,processed);}grid(xr,yr,style){return this.withStyle(style,()=>{const step=this.currentStyle.step||[1,1];const set=this.raphael.set();let x=step[0]*Math.ceil(xr[0]/step[0]);for(;x<=xr[1];x+=step[0]){set.push(this.line([x,yr[0]],[x,yr[1]]));}let y=step[1]*Math.ceil(yr[0]/step[1]);for(;y<=yr[1];y+=step[1]){set.push(this.line([xr[0],y],[xr[1],y]));}return set})}arc(center,radius,startAngle,endAngle,sector,style){return this.withStyle(style,()=>{startAngle=(startAngle%360+360)%360;endAngle=(endAngle%360+360)%360;const cent=this.scalePoint(center);const radii=this.scaleVector(radius);const startVector=polar$2(radius,startAngle);const endVector=polar$2(radius,endAngle);const round=x=>kmath.number.round(x,6);const startPoint=this.scalePoint([round(center[0]+startVector[0]),round(center[1]+startVector[1])]);const endPoint=this.scalePoint([round(center[0]+endVector[0]),round(center[1]+endVector[1])]);const largeAngle=((endAngle-startAngle)%360+360)%360>180;return this.raphael.path("M"+startPoint.join(" ")+"A"+radii.join(" ")+" 0 "+(largeAngle?1:0)+" 0 "+endPoint.join(" ")+(sector?"L"+cent.join(" ")+"z":""))})}circle(center,radius,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center),...this.scaleVector([radius,radius])))}rect(x,y,width,height,style){return this.withStyle(style,()=>{const corner=this.scalePoint([x,y+height]);const dims=this.scaleVector([width,height]);const elem=this.raphael.rect(...corner.concat(dims));if(this.isMobile){elem.node.style.shapeRendering="crispEdges";}return elem})}ellipse(center,radii,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center).concat(this.scaleVector(radii))))}fixedEllipse(center,radii,maxScale,padding,style){return this.withStyle(style,()=>{const scaledPoint=this.scalePoint(center);const scaledRadii=this.scaleVector(radii);const width=2*scaledRadii[0]*maxScale+padding;const height=2*scaledRadii[1]*maxScale+padding;const left=scaledPoint[0]-width/2;const top=scaledPoint[1]-height/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px"});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.ellipse(width/2,height/2,scaledRadii[0],scaledRadii[1]);return {wrapper:wrapper,visibleShape:visibleShape}})}unstyledPath(points){const p=this.raphael.path(this.svgPath(points));p.graphiePath=points;return p}path(points,style){return this.withStyle(style,()=>{return this.unstyledPath(points)})}fixedPath(points,center,createPath){points=points.map(this.scalePoint);center=center?this.scalePoint(center):null;createPath=createPath||this.svgPath;const xs=points.map(p=>p[0]);const ys=points.map(p=>p[1]);const pathLeft=Math.min(...xs);const pathRight=Math.max(...xs);const pathTop=Math.min(...ys);const pathBottom=Math.max(...ys);const padding=[4,4];const topLeftOfBoundingBox=[pathLeft,pathTop];points=points.map(function(point){return kmath.vector.add(kmath.vector.subtract(point,topLeftOfBoundingBox),kmath.vector.scale(padding,.5))});const width=pathRight-pathLeft+padding[0];const height=pathBottom-pathTop+padding[1];const left=topLeftOfBoundingBox[0]-padding[0]/2;const top=topLeftOfBoundingBox[1]-padding[1]/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:center?width/2+center[0]+"px "+(height/2+center[1])+"px":null});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.path(createPath(points));return {wrapper:wrapper,visibleShape:visibleShape}}scaledPath(points,style){return this.withStyle(style,()=>{const p=this.raphael.path(this.svgPath(points,true));p.graphiePath=points;return p})}line(start,end,style){return this.withStyle(style,()=>{const l=this.unstyledPath([start,end]);if(this.isMobile){l.node.style.shapeRendering="crispEdges";}return l})}parabola(a,b,c,style){return this.withStyle(style,()=>this.raphael.path(this.svgParabolaPath(a,b,c)))}fixedLine(start,end,thickness){const padding=[thickness,thickness];start=this.scalePoint(start);end=this.scalePoint(end);const extraOffset=[Math.min(start[0],end[0]),Math.min(start[1],end[1])];start=kmath.vector.add(kmath.vector.subtract(start,extraOffset),kmath.vector.scale(padding,.5));end=kmath.vector.add(kmath.vector.subtract(end,extraOffset),kmath.vector.scale(padding,.5));const left=extraOffset[0]-padding[0]/2;const top=extraOffset[1]-padding[1]/2;const width=Math.abs(start[0]-end[0])+padding[0];const height=Math.abs(start[1]-end[1])+padding[1];const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:start[0]+"px "+start[1]+"px"});const localRaphael=Raphael$1(wrapper,width,height);const path="M"+start[0]+" "+start[1]+" "+"L"+end[0]+" "+end[1];const visibleShape=localRaphael.path(path);visibleShape.graphiePath=[start,end];return {wrapper:wrapper,visibleShape:visibleShape}}sinusoid(a,b,c,d,style){return this.withStyle(style,()=>this.raphael.path(this.svgSinusoidPath(a,b,c,d)))}plotParametric(fn,range,style){return this.withStyle(style,()=>{const clip=xy=>{if(Math.abs(xy[1])>5e5){return [xy[0],Math.min(Math.max(xy[1],-5e5),5e5)]}return xy};const clippedFn=x=>clip(fn(x));const min=range[0];const max=range[1];let step=(max-min)/(this.currentStyle["plot-points"]||800);if(step===0){step=1;}const paths=this.raphael.set();let points=[];let lastY=clippedFn(min)[1];for(let t=min;t<=max;t+=step){const point=clippedFn(t);const y=point[1];if(y>0!==lastY>0&&Math.abs(y-lastY)>2*this.drawingTransform().pixelsPerUnitY()||isNaN(y)){paths.push(this.unstyledPath(points));points=[];}else {points.push(point);}lastY=y;}paths.push(this.unstyledPath(points));return paths})}plot(fn,range,style){return this.withStyle(style,()=>{const min=range[0];const max=range[1];if(!this.currentStyle["plot-points"]){this.currentStyle["plot-points"]=2*(max-min)*this.drawingTransform().pixelsPerUnitX();}const parametricFn=x=>[x,fn(x)];return this.plotParametric(parametricFn,range)})}withStyle(style,fn){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...this.processAttributes(style)};const result=this.postprocessDrawingResult(fn());this.currentStyle=oldStyle;return result}postprocessDrawingResult(result){const type=result.constructor.prototype;if(type===Raphael$1.el||type===Raphael$1.st){result.attr(this.currentStyle);if(this.currentStyle.arrows){result=this.addArrowheads(result);}}else if(result instanceof $__default.default){result.css({...this.currentStyle,...SVG_SPECIFIC_STYLE_MASK});}return result}addArrowheads(path){const type=path.constructor.prototype;if(type===Raphael$1.el){if(path.type==="path"&&typeof path.arrowheadsDrawn==="undefined"){const w=path.attr("stroke-width");const s=.6+.4*w;const l=path.getTotalLength();const set=this.raphael.set();const head=this.raphael.path(this.isMobile?"M-4,4 C-4,4 -0.25,0 -0.25,0 C-0.25,0 -4,-4 -4,-4":"M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4");const end=path.getPointAtLength(l-.4);const almostTheEnd=path.getPointAtLength(l-.75*s);const angle=Math.atan2(end.y-almostTheEnd.y,end.x-almostTheEnd.x)*180/Math.PI;const attrs=path.attr();delete attrs.path;let subpath=path.getSubpath(0,l-.75*s);subpath=this.raphael.path(subpath).attr(attrs);subpath.arrowheadsDrawn=true;path.remove();head.rotate(angle,this.isMobile?1e-5:.75,0).scale(s,s,.75,0).translate(almostTheEnd.x,almostTheEnd.y).attr(attrs).attr({"stroke-linejoin":"round","stroke-linecap":"round"});head.arrowheadsDrawn=true;set.push(subpath);set.push(head);return set}}else if(type===Raphael$1.st){for(let i=0,l=path.items.length;i<l;i++){this.addArrowheads(path.items[i]);}}return path}processAttributes(attrs){const transformers={scale:scale=>{this.drawingTransform().setScale(scale);},clipRect:pair=>{const point=pair[0];const size=pair[1];point[1]+=size[1];return {"clip-rect":this.scalePoint(point).concat(this.scaleVector(size)).join(" ")}},strokeWidth:function(val){return {"stroke-width":parseFloat(val)}},rx:val=>{return {rx:this.scaleVector([val,0])[0]}},ry:val=>{return {ry:this.scaleVector([0,val])[1]}},r:val=>{const scaled=this.scaleVector([val,val]);return {rx:scaled[0],ry:scaled[1]}}};const processed={};Object.entries(attrs||{}).forEach(function([key,value]){const transformer=transformers[key];if(typeof transformer==="function"){Object.assign(processed,transformer(value));}else {const dasherized=String(key).replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();processed[dasherized]=value;}});return processed}addMouseLayer(options){const localOptions={allowScratchpad:false,setDrawingAreaAvailable:function(){},...options};const mouselayerZIndex=2;this.mouselayer=Raphael$1(this.el,this.xpixels,this.ypixels);$__default.default(this.mouselayer.canvas).css("z-index",mouselayerZIndex);if(localOptions.onClick||localOptions.onMouseDown||localOptions.onMouseMove||localOptions.onMouseOver||localOptions.onMouseOut){const canvasClickTarget=this.mouselayer.rect(0,0,this.xpixels,this.ypixels).attr({fill:"#000",opacity:0});let isClickingCanvas=false;$__default.default(this.mouselayer.canvas).on("vmousedown",e=>{if(e.target===canvasClickTarget[0]){if(localOptions.onMouseDown){localOptions.onMouseDown(this.getMouseCoord(e));}isClickingCanvas=true;if(localOptions.onMouseMove){const handler=localOptions.onMouseMove;$__default.default(document).bind("vmousemove.mouseLayer",e=>{if(isClickingCanvas){e.preventDefault();handler(this.getMouseCoord(e));}});}$__default.default(document).bind("vmouseup.mouseLayer",e=>{$__default.default(document).unbind(".mouseLayer");if(isClickingCanvas&&localOptions.onClick){localOptions.onClick(this.getMouseCoord(e));}isClickingCanvas=false;});}});if(localOptions.onMouseOver){const handler=localOptions.onMouseOver;$__default.default(this.mouselayer.canvas).on("vmouseover",e=>{handler(this.getMouseCoord(e));});}if(localOptions.onMouseOut){const handler=localOptions.onMouseOut;$__default.default(this.mouselayer.canvas).on("vmouseout",e=>{handler(this.getMouseCoord(e));});}}if(!localOptions.allowScratchpad){localOptions.setDrawingAreaAvailable?.(false);}this._mouselayerWrapper=document.createElement("div");$__default.default(this._mouselayerWrapper).css({position:"absolute",left:0,top:0,zIndex:mouselayerZIndex});this._visiblelayerWrapper=document.createElement("div");$__default.default(this._visiblelayerWrapper).css({position:"absolute",left:0,top:0});const el=this.el;el.appendChild(this._visiblelayerWrapper);el.appendChild(this._mouselayerWrapper);this.addToMouseLayerWrapper=el=>{this._mouselayerWrapper?.appendChild(el);};this.addToVisibleLayerWrapper=el=>{this._visiblelayerWrapper?.appendChild(el);};}addToMouseLayerWrapper(el){throw new Error("addToMouseLayerWrapper is not ready. Call addMouseLayer() first.")}addToVisibleLayerWrapper(el){throw new Error("addToVisibleLayerWrapper is not ready. Call addMouseLayer() first.")}getMousePx(event){const offset=$__default.default(this.el).offset();const mouseX=event.pageX-offset.left;const mouseY=event.pageY-offset.top;return [mouseX,mouseY]}getMouseCoord(event){return this.unscalePoint(this.getMousePx(event))}constructor(el){Object.defineProperty(this,_bounds,{writable:true,value:void 0});Object.defineProperty(this,_drawingTransform,{writable:true,value:void 0});this.isMobile=false;this.currentStyle={"stroke-width":2,fill:"none"};this.label=(point,text,direction,arg4,arg5)=>{const style=typeof arg4==="object"?arg4:arg5;const latex=typeof arg4==="boolean"?arg4:true;return this.withStyle(style,()=>{const $span=$__default.default("<span>").addClass("graphie-label");const pad=this.currentStyle["label-distance"];$span.css({position:"absolute",padding:(pad!=null?pad:7)+"px",color:"black"}).data("labelDirection",direction).appendTo(this.el);$span.setPosition=point=>{const scaledPoint=this.scalePoint(point);$span.css({left:scaledPoint[0],top:scaledPoint[1]});};$span.setPosition(point);const span=$span[0];$span.processMath=function(math,force){processMath$1(span,math,force,function(){const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);});};$span.processText=function(text){$span.html(text);const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);};if(latex){$span.processMath(text,false);}else {$span.processText(text);}return $span})};this.svgPath=(points,alreadyScaled)=>{return points.map((point,i)=>{if(point===true){return "z"}const scaled=alreadyScaled?point:this.scalePoint(point);return (i===0?"M":"L")+kmath.KhanMath.bound(scaled[0])+" "+kmath.KhanMath.bound(scaled[1])}).join("")};this.svgParabolaPath=(a,b,c)=>{const computeParabola=function(x){return (a*x+b)*x+c};if(a===0){const points=[[this.bounds().xMin,computeParabola(this.bounds().xMin)],[this.bounds().xMax,computeParabola(this.bounds().xMax)]];return this.svgPath(points)}const xVertex=-b/(2*a);const distToEdge=Math.max(Math.abs(xVertex-this.bounds().xMin),Math.abs(xVertex-this.bounds().xMax));const xPoint=xVertex+distToEdge;const vertex=[xVertex,computeParabola(xVertex)];const point=[xPoint,computeParabola(xPoint)];const control=[vertex[0],vertex[1]-(point[1]-vertex[1])];const dx=Math.abs(vertex[0]-point[0]);const left=[vertex[0]-dx,point[1]];const right=[vertex[0]+dx,point[1]];const points=[left,control,right].map(this.scalePoint);const values=points.flat().map(kmath.KhanMath.bound);return "M"+values[0]+","+values[1]+" Q"+values[2]+","+values[3]+" "+values[4]+","+values[5]};this.svgSinusoidPath=(a,b,c,d)=>{const quarterPeriod=Math.abs(Math.PI/(2*b));const computeSine=function(x){return a*Math.sin(b*x-c)+d};const computeDerivative=function(x){return a*b*Math.cos(c-b*x)};const coordsForOffset=(initial,i)=>{const x0=initial+quarterPeriod*i;const x1=x0+quarterPeriod;const xCoords=[x0,x0*2/3+x1*1/3,x0*1/3+x1*2/3,x1];const yCoords=[computeSine(x0),computeSine(x0)+computeDerivative(x0)*(x1-x0)/3,computeSine(x1)-computeDerivative(x1)*(x1-x0)/3,computeSine(x1)];const points=kmath.vector.zip(xCoords,yCoords);return points.map(this.scalePoint)};const extent=this.bounds().width();const numQuarterPeriods=Math.ceil(extent/quarterPeriod)+1;let initial=c/b;const distToEdge=initial-this.bounds().xMin;initial-=quarterPeriod*Math.ceil(distToEdge/quarterPeriod);let coords=coordsForOffset(initial,0);let path="M"+coords[0][0]+","+coords[0][1]+" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];for(let i=1;i<numQuarterPeriods;i++){coords=coordsForOffset(initial,i);path+=" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];}return path};this.scalePoint=point=>{return this.drawingTransform().scalePoint(point)};this.scaleVector=point=>{return this.drawingTransform().scaleVector(point)};this.unscalePoint=point=>{return this.drawingTransform().unscalePoint(point)};this.unscaleVector=point=>{return this.drawingTransform().unscaleVector(point)};this.el=el;$__default.default(el).css("position","relative");this.raphael=Raphael$1(el);$__default.default(el).attr("aria-hidden","true");$__default.default(el).children("div").css("position","absolute");}};const labelDirections={center:[-0.5,-0.5],above:[-0.5,-1],"above right":[0,-1],right:[0,-0.5],"below right":[0,0],below:[-0.5,0],"below left":[-1,0],left:[-1,-0.5],"above left":[-1,-1]};function normalizeRange(range){function normalizeInterval(magnitude){if(typeof magnitude==="number"){return [-magnitude,magnitude]}else {return magnitude}}function getXAndYRanges(range){if(Array.isArray(range)){return range}else {return [range,range]}}if(range==null){return range}const[xRange,yRange]=getXAndYRanges(range);return [normalizeInterval(xRange),normalizeInterval(yRange)]}function toPair(x){if(Array.isArray(x)){return x}return [x,x]}const SVG_SPECIFIC_STYLE_MASK={"stroke-width":null};const setLabelMargins=function(span,size){const $span=$__default.default(span);const direction=$span.data("labelDirection");let[width,height]=size;if(width===0&&height===0){[width,height]=[1,1];Log.log("Label size was 0x0 in graphie.js; using 1x1 instead");}$span.css("visibility","");if(typeof direction==="number"){const x=Math.cos(direction);const y=Math.sin(direction);const scale=Math.min(width/2/Math.abs(x),height/2/Math.abs(y));$span.css({marginLeft:-width/2+x*scale,marginTop:-height/2-y*scale});}else {const currentHeightMatchesProps=span.scrollHeight===height;const $svgImage=$span.closest(".svg-image");const $graphie=$span.closest(".graphie");const $container=$svgImage.length>0?$svgImage:$graphie;$container.css("line-height","normal");if(currentHeightMatchesProps&&span.scrollHeight!==height){height=span.scrollHeight;}const widthValues=$container.css(["max-width","width"])??{"max-width":"0px"};const expectedWidth=widthValues["max-width"]!=="none"?widthValues["max-width"]:widthValues["width"];let scale=($container.width()??0)/parseInt(expectedWidth.replace(/px$/,""));if(isNaN(scale)){scale=1;}else if(scale===0){scale=1;}const padding=$span.css("padding")??"0px";const currentPadding=padding!=="none"?padding:"0px";const rawPadding=parseInt(currentPadding.replace(/px$/,""));let normalizedWidth=width;let normalizedHeight=height;const imageScale=Number($container.attr("data-scale"));const hasValidImageScale=!Number.isNaN(imageScale)&&imageScale>=0;if(hasValidImageScale){scale=scale*imageScale;const totalPadding=2*rawPadding;normalizedWidth=(width-totalPadding)/imageScale+totalPadding;normalizedHeight=(height-totalPadding)/imageScale+totalPadding;}const newPadding=rawPadding*scale;const multipliers=labelDirections[direction||"center"];const styling={marginLeft:normalizedWidth*multipliers[0]*scale,marginTop:normalizedHeight*multipliers[1]*scale,padding:`${newPadding}px`,fontSize:`${scale*100}%`};$span.css(styling);}};const GraphUtils={Graphie: Graphie$1,createGraphie:function(el){return new Graphie$1(el)},unscaledSvgPath:function(points){if(points[0]===true){return ""}return points.map(function(point,i){if(point===true){return "z"}return (i===0?"M":"L")+point[0]+" "+point[1]}).join("")},getDistance:function(point1,point2){return kmath.point.distanceToPoint(point1,point2)},findAngleDeprecated:function(point1,point2,vertex){if(vertex===undefined){const x=point1[0]-point2[0];const y=point1[1]-point2[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360}return GraphUtils.findAngleDeprecated(point1,vertex)-GraphUtils.findAngleDeprecated(point2,vertex)},graphs:{}};
1602
1614
 
1603
1615
  (function($,window1,document1,undefined$1){if(typeof $==="undefined"){return}var dataPropertyName="virtualMouseBindings",touchTargetPropertyName="virtualTouchID",virtualEventNames="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),touchEventProps="clientX clientY pageX pageY screenX screenY".split(" "),mouseHookProps=$.event.mouseHooks?$.event.mouseHooks.props:[],mouseEventProps=$.event.props.concat(mouseHookProps),activeDocHandlers={},resetTimerID=0,startX=0,startY=0,didScroll=false,clickBlockList=[],blockMouseTriggers=false,blockTouchTriggers=false,eventCaptureSupported="addEventListener"in document1,$document=$(document1),nextTouchID=1,lastTouchID=0;$.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500};function getNativeEvent(event){while(event&&typeof event.originalEvent!=="undefined"){event=event.originalEvent;}return event}function createVirtualEvent(event,eventType){var t=event.type,oe,props,ne,prop,ct,touch,i,j,len;event=$.Event(event);event.type=eventType;oe=event.originalEvent;props=$.event.props;if(t.search(/mouse/)>-1){props=mouseEventProps;}if(oe){for(i=props.length,prop;i;){prop=props[--i];event[prop]=oe[prop];}}if(t.search(/mouse(down|up)|click/)>-1&&!event.which){event.which=1;}if(t.search(/^touch/)!==-1){ne=getNativeEvent(oe);t=ne.touches;ct=ne.changedTouches;touch=t&&t.length?t[0]:ct&&ct.length?ct[0]:undefined$1;if(touch){for(j=0,len=touchEventProps.length;j<len;j++){prop=touchEventProps[j];event[prop]=touch[prop];}}}return event}function getVirtualBindingFlags(element){var flags={},b,k;while(element){b=$.data(element,dataPropertyName);for(k in b){if(b[k]){flags[k]=flags.hasVirtualBinding=true;}}element=element.parentNode;}return flags}function getClosestElementWithVirtualBinding(element,eventType){var b;while(element){b=$.data(element,dataPropertyName);if(b&&(!eventType||b[eventType])){return element}element=element.parentNode;}return null}function enableTouchBindings(){blockTouchTriggers=false;}function disableTouchBindings(){blockTouchTriggers=true;}function enableMouseBindings(){lastTouchID=0;clickBlockList.length=0;blockMouseTriggers=false;disableTouchBindings();}function disableMouseBindings(){enableTouchBindings();}function startResetTimer(){clearResetTimer();resetTimerID=setTimeout(function(){resetTimerID=0;enableMouseBindings();},$.vmouse.resetTimerDuration);}function clearResetTimer(){if(resetTimerID){clearTimeout(resetTimerID);resetTimerID=0;}}function triggerVirtualEvent(eventType,event,flags){var ve;if(flags&&flags[eventType]||!flags&&getClosestElementWithVirtualBinding(event.target,eventType)){ve=createVirtualEvent(event,eventType);$(event.target).trigger(ve);}return ve}function mouseEventCallback(event){var touchID=$.data(event.target,touchTargetPropertyName);if(!blockMouseTriggers&&(!lastTouchID||lastTouchID!==touchID)){var ve=triggerVirtualEvent("v"+event.type,event);if(ve){if(ve.isDefaultPrevented()){event.preventDefault();}if(ve.isPropagationStopped()){event.stopPropagation();}if(ve.isImmediatePropagationStopped()){event.stopImmediatePropagation();}}}}function handleTouchStart(event){var touches=getNativeEvent(event).touches,target,flags;if(touches&&touches.length===1){target=event.target;flags=getVirtualBindingFlags(target);if(flags.hasVirtualBinding){lastTouchID=nextTouchID++;$.data(target,touchTargetPropertyName,lastTouchID);clearResetTimer();disableMouseBindings();didScroll=false;var t=getNativeEvent(event).touches[0];startX=t.pageX;startY=t.pageY;triggerVirtualEvent("vmouseover",event,flags);triggerVirtualEvent("vmousedown",event,flags);}}}function handleScroll(event){if(blockTouchTriggers){return}if(!didScroll){triggerVirtualEvent("vmousecancel",event,getVirtualBindingFlags(event.target));}didScroll=true;startResetTimer();}function handleTouchMove(event){if(blockTouchTriggers){return}var t=getNativeEvent(event).touches[0],didCancel=didScroll,moveThreshold=$.vmouse.moveDistanceThreshold,didScroll=didScroll||Math.abs(t.pageX-startX)>moveThreshold||Math.abs(t.pageY-startY)>moveThreshold,flags=getVirtualBindingFlags(event.target);if(didScroll&&!didCancel){triggerVirtualEvent("vmousecancel",event,flags);}triggerVirtualEvent("vmousemove",event,flags);startResetTimer();}function handleTouchEnd(event){if(blockTouchTriggers){return}disableTouchBindings();var flags=getVirtualBindingFlags(event.target),t;triggerVirtualEvent("vmouseup",event,flags);if(!didScroll){var ve=triggerVirtualEvent("vclick",event,flags);if(ve&&ve.isDefaultPrevented()){t=getNativeEvent(event).changedTouches[0];clickBlockList.push({touchID:lastTouchID,x:t.clientX,y:t.clientY});blockMouseTriggers=true;}}triggerVirtualEvent("vmouseout",event,flags);didScroll=false;startResetTimer();}function hasVirtualBindings(ele){var bindings=$.data(ele,dataPropertyName),k;if(bindings){for(k in bindings){if(bindings[k]){return true}}}return false}function dummyMouseHandler(){}function getSpecialEventObject(eventType){var realType=eventType.substr(1);return {setup:function(data,namespace){if(!hasVirtualBindings(this)){$.data(this,dataPropertyName,{});}var bindings=$.data(this,dataPropertyName);bindings[eventType]=true;activeDocHandlers[eventType]=(activeDocHandlers[eventType]||0)+1;if(activeDocHandlers[eventType]===1){$document.bind(realType,mouseEventCallback);}$(this).bind(realType,dummyMouseHandler);if(eventCaptureSupported){activeDocHandlers["touchstart"]=(activeDocHandlers["touchstart"]||0)+1;if(activeDocHandlers["touchstart"]===1){$document.bind("touchstart",handleTouchStart).bind("touchend",handleTouchEnd).bind("touchmove",handleTouchMove).bind("scroll",handleScroll);}}},teardown:function(data,namespace){--activeDocHandlers[eventType];if(!activeDocHandlers[eventType]){$document.unbind(realType,mouseEventCallback);}if(eventCaptureSupported){--activeDocHandlers["touchstart"];if(!activeDocHandlers["touchstart"]){$document.unbind("touchstart",handleTouchStart).unbind("touchmove",handleTouchMove).unbind("touchend",handleTouchEnd).unbind("scroll",handleScroll);}}var $this=$(this),bindings=$.data(this,dataPropertyName);if(bindings){bindings[eventType]=false;}$this.unbind(realType,dummyMouseHandler);if(!hasVirtualBindings(this)){$this.removeData(dataPropertyName);}}}}for(var i=0;i<virtualEventNames.length;i++){$.event.special[virtualEventNames[i]]=getSpecialEventObject(virtualEventNames[i]);}if(eventCaptureSupported){document1.addEventListener("click",function(e){var cnt=clickBlockList.length,target=e.target,x,y,ele,i,o;if(cnt){x=e.clientX;y=e.clientY;threshold=$.vmouse.clickDistanceThreshold;ele=target;while(ele){for(i=0;i<cnt;i++){o=clickBlockList[i];if(ele===target&&Math.abs(o.x-x)<threshold&&Math.abs(o.y-y)<threshold||$.data(ele,touchTargetPropertyName)===o.touchID){e.preventDefault();e.stopPropagation();return}}ele=ele.parentNode;}}},true);}})($__default.default,window,document);
1604
1616
 
@@ -1650,7 +1662,7 @@ const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=({imgElement,width,height,
1650
1662
 
1651
1663
  const ZoomImageButton=({imgElement,imgSrc,width,height})=>{const i18n=usePerseusI18n();const handleClick=(event,openModal)=>{const mouseEvent=event;if(mouseEvent.metaKey||mouseEvent.ctrlKey){window.open(imgSrc,"_blank");}else {openModal();}};return jsxRuntimeExports.jsx(wonderBlocksModal.ModalLauncher,{modal:({closeModal})=>jsxRuntimeExports.jsx(ZoomedImageView,{imgElement:imgElement,width:width,height:height,onClose:closeModal}),children:({openModal})=>jsxRuntimeExports.jsx(Clickable__default.default,{"aria-label":i18n.strings.imageZoomAriaLabel,onClick:event=>handleClick(event,openModal),style:{position:"absolute",width:"100%",height:"100%",overflow:"hidden",cursor:"zoom-in"},children:()=>{return jsxRuntimeExports.jsx(React__namespace.Fragment,{})}})})};
1652
1664
 
1653
- function isImageProbablyPhotograph(imageUrl){return /\.(jpg|jpeg)$/i.test(imageUrl)}function defaultPreloader(dimensions){return jsxRuntimeExports.jsx("span",{style:{top:0,left:0,width:"100%",height:"100%",position:"absolute",minWidth:"20px",display:"flex",justifyContent:"center",alignContent:"center"},children:jsxRuntimeExports.jsx(wonderBlocksProgressSpinner.CircularSpinner,{size:"medium"})})}class SvgImage extends React__namespace.Component{componentDidMount(){this._isMounted=true;if(Util.isLabeledSVG(this.props.src)){this.loadResources();}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.src!==nextProps.src){this._isLoadingGraphie=false;this.setState({imageLoaded:false,dataLoaded:false});}}shouldComponentUpdate(nextProps,nextState){if(!___default.default.isEqual(this.props,nextProps)){return true}const wasLoaded=this.isLoadedInState(this.state);const nextLoaded=this.isLoadedInState(nextState);return wasLoaded!==nextLoaded}componentDidUpdate(prevProps,prevState){const wasLoaded=this.isLoadedInState(prevState);const isLoaded=this.isLoadedInState(this.state);if(Util.isLabeledSVG(this.props.src)&&!isLoaded&&!this._isLoadingGraphie){this.loadResources();}if(!wasLoaded&&isLoaded){this.props.setAssetStatus(this.props.src,true);}}componentWillUnmount(){this._isMounted=false;}isLoadedInState(state){return Util.isLabeledSVG(this.props.src)?state.imageLoaded&&state.dataLoaded:state.imageLoaded}loadResources(){this._isLoadingGraphie=true;loadGraphie(this.props.src,(data,localized)=>{this._isLoadingGraphie=false;if(this._isMounted&&data.labels&&data.range){const labelsRendered={};data.labels.forEach(label=>{labelsRendered[label.content]=false;});this.setState({dataLoaded:true,labelDataIsLocalized:localized,labelsRendered,labels:data.labels,range:data.range});}});}sizeProvided(){return this.props.width!=null&&this.props.height!=null}_tryGetPixels(value){value=value||"";if(!value.endsWith("px")){return null}return parseFloat(value)||null}render(){const imageSrc=this.props.src;const imageProps={alt:this.props.alt,title:this.props.title};const width=this.props.width&&this.props.width*this.props.scale;const height=this.props.height&&this.props.height*this.props.scale;const dimensions={width,height};const responsive=this.props.responsive&&!!(width&&height);let extraGraphie;if(this.props.extraGraphie&&this.props.extraGraphie.labels.length){extraGraphie=jsxRuntimeExports.jsx(Graphie,{box:this.props.extraGraphie.box,range:this.props.extraGraphie.range,options:{labels:this.props.extraGraphie.labels},responsive:true,addMouseLayer:false,setup:this.setupGraphie});}const preloaderBaseFunc=this.props.preloader===undefined?defaultPreloader:this.props.preloader;const preloader=preloaderBaseFunc?()=>preloaderBaseFunc(dimensions):null;if(!Util.isLabeledSVG(imageSrc)){if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,imgProps:imageProps,preloader:preloader,onUpdate:this.handleUpdate}),extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,allowFullBleed:this.props.allowFullBleed&&isImageProbablyPhotograph(imageSrc),children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{imgElement:imageContent,imgSrc:imageSrc,width:width,height:height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,preloader:preloader,imgProps:imageProps,onUpdate:this.handleUpdate})}const imageUrl=Util.getSvgUrl(imageSrc);let graphie;if(this.isLoadedInState(this.state)){let box;if(this.sizeProvided()){box=[width,height];}else if(this.state.imageDimensions){box=[this.state.imageDimensions[0]*this.props.scale,this.state.imageDimensions[1]*this.props.scale];}else {throw new perseusCore.PerseusError("svg-image has no dimensions",perseusCore.Errors.InvalidInput,{metadata:{src:this.props.src}})}graphie=jsxRuntimeExports.jsx(Graphie,{ref:"graphie",box:box,scale:[40*this.props.scale,40*this.props.scale],range:this.state.range,options:___default.default.pick(this.state,"labels"),responsive:responsive,addMouseLayer:false,setup:this.setupGraphie});}if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie,extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{imgElement:imageContent,imgSrc:imageUrl,width:width,height:height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsxs("div",{className:"unresponsive-svg-image",style:dimensions,children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie]})}constructor(props){super(props),this.onImageLoad=()=>{if(this.sizeProvided()){this.setState({imageLoaded:true});}else {Util.getImageSize(this.props.src,(width,height)=>{if(this._isMounted){this.setState({imageLoaded:true,imageDimensions:[width,height]});}});}},this.setupGraphie=(graphie,options)=>{___default.default.map(options.labels,labelData=>{const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.state.labelDataIsLocalized){const elem=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,false);getDependencies().svgImageJiptLabels.addLabel(elem,labelData.typesetAsMath);}else if(labelData.coordinates){const styling=this.props.scale!==1?{"font-size":100*this.props.scale+"%"}:null;const label=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,labelData.typesetAsMath,styling);const labelStyle=label[0].style;let labelTop=this._tryGetPixels(labelStyle.top);let labelLeft=this._tryGetPixels(labelStyle.left);if(labelTop===null||labelLeft===null){const labelPosition=label.position();labelTop=labelPosition.top;labelLeft=labelPosition.left;}const svgHeight=(this.props.height||0)*this.props.scale;const svgWidth=(this.props.width||0)*this.props.scale;label.css({top:labelTop/svgHeight*100+"%",left:labelLeft/svgWidth*100+"%"});___default.default.each(labelData.style,(styleValue,styleName)=>{label.css(styleName,styleValue);});}this.setState({labelsRendered:{...this.state.labelsRendered,[labelData.content]:true}});});},this.handleUpdate=status=>{this.props.onUpdate();if(!Util.isLabeledSVG(this.props.src)&&status==="loaded"){this.setState({imageLoaded:true});}};props.setAssetStatus(props.src,false);this._isMounted=false;this._isLoadingGraphie=false;this.state={imageLoaded:false,imageDimensions:null,dataLoaded:false,labelDataIsLocalized:false,labels:[],labelsRendered:{},range:[[0,0],[0,0]]};}}SvgImage.contextType=PerseusI18nContext;SvgImage.defaultProps={constrainHeight:false,onUpdate:()=>{},responsive:true,src:"",scale:1,zoomToFullSizeOnMobile:false,setAssetStatus:(src,status)=>{}};
1665
+ function isImageProbablyPhotograph(imageUrl){return /\.(jpg|jpeg)$/i.test(imageUrl)}function defaultPreloader(dimensions){return jsxRuntimeExports.jsx("span",{style:{top:0,left:0,width:"100%",height:"100%",position:"absolute",minWidth:"20px",display:"flex",justifyContent:"center",alignContent:"center"},children:jsxRuntimeExports.jsx(wonderBlocksProgressSpinner.CircularSpinner,{size:"medium"})})}class SvgImage extends React__namespace.Component{componentDidMount(){this._isMounted=true;if(Util.isLabeledSVG(this.props.src)){this.loadResources();}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.src!==nextProps.src){this._isLoadingGraphie=false;this.setState({imageLoaded:false,dataLoaded:false});}}shouldComponentUpdate(nextProps,nextState){if(!___default.default.isEqual(this.props,nextProps)){return true}const wasLoaded=this.isLoadedInState(this.state);const nextLoaded=this.isLoadedInState(nextState);return wasLoaded!==nextLoaded}componentDidUpdate(prevProps,prevState){const wasLoaded=this.isLoadedInState(prevState);const isLoaded=this.isLoadedInState(this.state);if(Util.isLabeledSVG(this.props.src)&&!isLoaded&&!this._isLoadingGraphie){this.loadResources();}if(!wasLoaded&&isLoaded){this.props.setAssetStatus(this.props.src,true);}}componentWillUnmount(){this._isMounted=false;}isLoadedInState(state){return Util.isLabeledSVG(this.props.src)?state.imageLoaded&&state.dataLoaded:state.imageLoaded}loadResources(){this._isLoadingGraphie=true;loadGraphie(this.props.src,(data,localized)=>{this._isLoadingGraphie=false;if(this._isMounted&&data.labels&&data.range){const labelsRendered={};data.labels.forEach(label=>{labelsRendered[label.content]=false;});this.setState({dataLoaded:true,labelDataIsLocalized:localized,labelsRendered,labels:data.labels,range:data.range});}});}sizeProvided(){return this.props.width!=null&&this.props.height!=null}_tryGetPixels(value){value=value||"";if(!value.endsWith("px")){return null}return parseFloat(value)||null}render(){const imageSrc=this.props.src;const imageProps={alt:this.props.alt,title:this.props.title};const width=this.props.width&&this.props.width*this.props.scale;const height=this.props.height&&this.props.height*this.props.scale;const dimensions={width,height};const responsive=this.props.responsive&&!!(width&&height);let extraGraphie;if(this.props.extraGraphie&&this.props.extraGraphie.labels.length){extraGraphie=jsxRuntimeExports.jsx(Graphie,{box:this.props.extraGraphie.box,range:this.props.extraGraphie.range,options:{labels:this.props.extraGraphie.labels},responsive:true,addMouseLayer:false,setup:this.setupGraphie});}const preloaderBaseFunc=this.props.preloader===undefined?defaultPreloader:this.props.preloader;const preloader=preloaderBaseFunc?()=>preloaderBaseFunc(dimensions):null;if(!Util.isLabeledSVG(imageSrc)){if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,imgProps:imageProps,preloader:preloader,onUpdate:this.handleUpdate}),extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,allowFullBleed:this.props.allowFullBleed&&isImageProbablyPhotograph(imageSrc),scale:this.props.scale,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{imgElement:imageContent,imgSrc:imageSrc,width:width,height:height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,preloader:preloader,imgProps:imageProps,onUpdate:this.handleUpdate})}const imageUrl=Util.getSvgUrl(imageSrc);let graphie;if(this.isLoadedInState(this.state)){let box;if(this.sizeProvided()){box=[width,height];}else if(this.state.imageDimensions){box=[this.state.imageDimensions[0]*this.props.scale,this.state.imageDimensions[1]*this.props.scale];}else {throw new perseusCore.PerseusError("svg-image has no dimensions",perseusCore.Errors.InvalidInput,{metadata:{src:this.props.src}})}graphie=jsxRuntimeExports.jsx(Graphie,{ref:"graphie",box:box,scale:[40*this.props.scale,40*this.props.scale],range:this.state.range,options:___default.default.pick(this.state,"labels"),responsive:responsive,addMouseLayer:false,setup:this.setupGraphie});}if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie,extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,scale:this.props.scale,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{imgElement:imageContent,imgSrc:imageUrl,width:width,height:height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsxs("div",{className:"unresponsive-svg-image",style:dimensions,children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie]})}constructor(props){super(props),this.onImageLoad=()=>{if(this.sizeProvided()){this.setState({imageLoaded:true});}else {Util.getImageSize(this.props.src,(width,height)=>{if(this._isMounted){this.setState({imageLoaded:true,imageDimensions:[width,height]});}});}},this.setupGraphie=(graphie,options)=>{___default.default.map(options.labels,labelData=>{const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.state.labelDataIsLocalized){const elem=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,false);getDependencies().svgImageJiptLabels.addLabel(elem,labelData.typesetAsMath);}else if(labelData.coordinates){const styling=this.props.scale!==1?{"font-size":100*this.props.scale+"%"}:null;const label=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,labelData.typesetAsMath,styling);const labelStyle=label[0].style;let labelTop=this._tryGetPixels(labelStyle.top);let labelLeft=this._tryGetPixels(labelStyle.left);if(labelTop===null||labelLeft===null){const labelPosition=label.position();labelTop=labelPosition.top;labelLeft=labelPosition.left;}const svgHeight=(this.props.height||0)*this.props.scale;const svgWidth=(this.props.width||0)*this.props.scale;label.css({top:labelTop/svgHeight*100+"%",left:labelLeft/svgWidth*100+"%"});___default.default.each(labelData.style,(styleValue,styleName)=>{label.css(styleName,styleValue);});}this.setState({labelsRendered:{...this.state.labelsRendered,[labelData.content]:true}});});},this.handleUpdate=status=>{this.props.onUpdate();if(!Util.isLabeledSVG(this.props.src)&&status==="loaded"){this.setState({imageLoaded:true});}};props.setAssetStatus(props.src,false);this._isMounted=false;this._isLoadingGraphie=false;this.state={imageLoaded:false,imageDimensions:null,dataLoaded:false,labelDataIsLocalized:false,labels:[],labelsRendered:{},range:[[0,0],[0,0]]};}}SvgImage.contextType=PerseusI18nContext;SvgImage.defaultProps={constrainHeight:false,onUpdate:()=>{},responsive:true,src:"",scale:1,zoomToFullSizeOnMobile:false,setAssetStatus:(src,status)=>{}};
1654
1666
 
1655
1667
  class Tex extends React__namespace.Component{render(){const{TeX:BaseTeX}=getDependencies();return jsxRuntimeExports.jsx(BaseTeX,{onRender:this.handleRender,children:this.props.children})}constructor(props){super(props),this.handleRender=()=>{this.setState({rendered:true});this.props.onRender();if(!this._hasRendered){this._hasRendered=true;this.props.setAssetStatus(this.props.children,true);}};this.props.setAssetStatus(this.props.children,false);this.state={rendered:false};this._hasRendered=false;}}Tex.defaultProps={onRender:()=>{},setAssetStatus:(src,status)=>{}};
1656
1668
 
@@ -2088,7 +2100,7 @@ var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,D
2088
2100
 
2089
2101
  const init=function(){registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
2090
2102
 
2091
- const libName="@khanacademy/perseus";const libVersion="76.0.2";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
2103
+ const libName="@khanacademy/perseus";const libVersion="76.0.3";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
2092
2104
 
2093
2105
  const apiVersion={major:12,minor:0};
2094
2106