@khanacademy/perseus 71.0.0 → 71.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -28,6 +28,7 @@ import { entries, UnreachableCaseError, keys } from '@khanacademy/wonder-stuff-c
28
28
  import SimpleMarkdown from '@khanacademy/simple-markdown';
29
29
  import { pureMarkdownRules, traverseContent } from '@khanacademy/pure-markdown';
30
30
  import { announceMessage } from '@khanacademy/wonder-blocks-announcer';
31
+ import { useTimeout } from '@khanacademy/wonder-blocks-timing';
31
32
  import IconButton from '@khanacademy/wonder-blocks-icon-button';
32
33
  import caretLeftIcon from '@phosphor-icons/core/regular/caret-left.svg';
33
34
  import caretRightIcon from '@phosphor-icons/core/regular/caret-right.svg';
@@ -1517,7 +1518,7 @@ function _class_private_field_loose_key(name) {
1517
1518
  * Licensed under the MIT (http://raphaeljs.com/license.html) license.
1518
1519
  */var Raphael$1 = (function(){var setAttr;if("".trim){setAttr=function(node,att,value){node.setAttribute(att,String(value).trim());};}else {setAttr=function(node,att,value){node.setAttribute(att,String(value));};}function R(){if(R.is(arguments[0],array)){var a=arguments[0],cnv=create[apply](R,a.splice(0,3+R.is(a[0],nu))),res=cnv.set();for(var i=0,ii1=a[length];i<ii1;i++){var j=a[i]||{};elements[has](j.type)&&res[push](cnv[j.type]().attr(j));}return res}return create[apply](R,arguments)}R.version="1.5.2";var separator=/[, ]+/,elements={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},formatrg=/\{(\d+)\}/g,proto="prototype",has="hasOwnProperty",doc=document,win=window,oldRaphael={was:Object[proto][has].call(win,"Raphael"),is:win.Raphael},Paper=function(){this.customAttributes={};},paperproto,appendChild="appendChild",apply="apply",concat="concat",supportsTouch="createTouch"in doc,E="",S=" ",Str=String,split="split",events="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend"[split](S),touchMap={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},join="join",length="length",lowerCase=Str[proto].toLowerCase,math=Math,mmax=math.max,mmin=math.min,abs=math.abs,pow=math.pow,PI=math.PI,nu="number",string="string",array="array",toString="toString",fillString="fill",objectToString=Object[proto][toString],push="push",ISURL=/^url\(['"]?([^\)]+?)['"]?\)$/i,colourRegExp=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,isnan={"NaN":1,"Infinity":1,"-Infinity":1},bezierrg=/^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,round=math.round,toFloat=parseFloat,toInt=parseInt,ms=" progid:DXImageTransform.Microsoft",upperCase=Str[proto].toUpperCase,availableAttrs={blur:0,"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/",opacity:1,path:"M0,0",r:0,rotation:0,rx:0,ry:0,scale:"1 1",src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",translation:"0 0",width:0,x:0,y:0},availableAnimAttrs={along:"along",blur:nu,"clip-rect":"csv",cx:nu,cy:nu,fill:"colour","fill-opacity":nu,"font-size":nu,height:nu,opacity:nu,path:"path",r:nu,rotation:"csv",rx:nu,ry:nu,scale:"csv",stroke:"colour","stroke-opacity":nu,"stroke-width":nu,translation:"csv",width:nu,x:nu,y:nu},rp="replace",animKeyFrames=/^(from|to|\d+%?)$/,commaSpaces=/\s*,\s*/,hsrg={hs:1,rg:1},p2s=/,?([achlmqrstvxz]),?/gi,pathCommand=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,pathValues=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,radial_gradient=/^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/,sortByKey=function(a,b){return a.key-b.key};R.type=win.SVGAngle||doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML";if(R.type=="VML"){var d=doc.createElement("div"),b;d.innerHTML='<v:shape adj="1"/>';b=d.firstChild;b.style.behavior="url(#default#VML)";if(!(b&&typeof b.adj=="object")){return R.type=null}d=null;}R.svg=!(R.vml=R.type=="VML");Paper[proto]=R[proto];paperproto=Paper[proto];R._id=0;R._oid=0;R.fn={};R.is=function(o,type){type=lowerCase.call(type);if(type=="finite"){return !isnan[has](+o)}return type=="null"&&o===null||type==typeof o||type=="object"&&o===Object(o)||type=="array"&&Array.isArray&&Array.isArray(o)||objectToString.call(o).slice(8,-1).toLowerCase()==type};R.angle=function(x1,y1,x2,y2,x3,y3){if(x3==null){var x=x1-x2,y=y1-y2;if(!x&&!y){return 0}return ((x<0)*180+math.atan(-y/-x)*180/PI+360)%360}else {return R.angle(x1,y1,x3,y3)-R.angle(x2,y2,x3,y3)}};R.rad=function(deg){return deg%360*PI/180};R.deg=function(rad){return rad*180/PI%360};R.snapTo=function(values,value,tolerance){tolerance=R.is(tolerance,"finite")?tolerance:10;if(R.is(values,array)){var i=values.length;while(i--)if(abs(values[i]-value)<=tolerance){return values[i]}}else {values=+values;var rem=value%values;if(rem<tolerance){return value-rem}if(rem>values-tolerance){return value-rem+values}}return value};function createUUID(){var s=[],i=0;for(;i<32;i++){s[i]=(~~(math.random()*16))[toString](16);}s[12]=4;s[16]=(s[16]&3|8)[toString](16);return "r-"+s[join]("")}R.setWindow=function(newwin){win=newwin;doc=win.document;};var toHex=function(color){if(R.vml){var trim=/^\s+|\s+$/g;var bod;try{var docum=new ActiveXObject("htmlfile");docum.write("<body>");docum.close();bod=docum.body;}catch(e){bod=createPopup().document.body;}var range=bod.createTextRange();toHex=cacher(function(color){try{bod.style.color=Str(color)[rp](trim,E);var value=range.queryCommandValue("ForeColor");value=(value&255)<<16|value&65280|(value&0xff0000)>>>16;return "#"+("000000"+value[toString](16)).slice(-6)}catch(e){return "none"}});}else {var i=doc.createElement("i");i.title="Raphaël Colour Picker";i.style.display="none";doc.body[appendChild](i);toHex=cacher(function(color){i.style.color=color;return doc.defaultView.getComputedStyle(i,E).getPropertyValue("color")});}return toHex(color)},hsbtoString=function(){return "hsb("+[this.h,this.s,this.b]+")"},hsltoString=function(){return "hsl("+[this.h,this.s,this.l]+")"},rgbtoString=function(){return this.hex};R.hsb2rgb=function(h,s,b,o){if(R.is(h,"object")&&"h"in h&&"s"in h&&"b"in h){b=h.b;s=h.s;h=h.h;o=h.o;}return R.hsl2rgb(h,s,b/2,o)};R.hsl2rgb=function(h,s,l,o){if(R.is(h,"object")&&"h"in h&&"s"in h&&"l"in h){l=h.l;s=h.s;h=h.h;}if(h>1||s>1||l>1){h/=360;s/=100;l/=100;}var rgb={},channels=["r","g","b"],t2,t1,t3;if(!s){rgb={r:l,g:l,b:l};}else {if(l<.5){t2=l*(1+s);}else {t2=l+s-l*s;}t1=2*l-t2;for(var i=0;i<3;i++){t3=h+1/3*-(i-1);t3<0&&t3++;t3>1&&t3--;if(t3*6<1){rgb[channels[i]]=t1+(t2-t1)*6*t3;}else if(t3*2<1){rgb[channels[i]]=t2;}else if(t3*3<2){rgb[channels[i]]=t1+(t2-t1)*(2/3-t3)*6;}else {rgb[channels[i]]=t1;}}}rgb.r*=255;rgb.g*=255;rgb.b*=255;rgb.hex="#"+(0x1000000|rgb.b|rgb.g<<8|rgb.r<<16).toString(16).slice(1);R.is(o,"finite")&&(rgb.opacity=o);rgb.toString=rgbtoString;return rgb};R.rgb2hsb=function(red,green,blue){if(green==null&&R.is(red,"object")&&"r"in red&&"g"in red&&"b"in red){blue=red.b;green=red.g;red=red.r;}if(green==null&&R.is(red,string)){var clr=R.getRGB(red);red=clr.r;green=clr.g;blue=clr.b;}if(red>1||green>1||blue>1){red/=255;green/=255;blue/=255;}var max=mmax(red,green,blue),min=mmin(red,green,blue),hue,saturation,brightness=max;if(min==max){return {h:0,s:0,b:max,toString:hsbtoString}}else {var delta=max-min;saturation=delta/max;if(red==max){hue=(green-blue)/delta;}else if(green==max){hue=2+(blue-red)/delta;}else {hue=4+(red-green)/delta;}hue/=6;hue<0&&hue++;hue>1&&hue--;}return {h:hue,s:saturation,b:brightness,toString:hsbtoString}};R.rgb2hsl=function(red,green,blue){if(green==null&&R.is(red,"object")&&"r"in red&&"g"in red&&"b"in red){blue=red.b;green=red.g;red=red.r;}if(green==null&&R.is(red,string)){var clr=R.getRGB(red);red=clr.r;green=clr.g;blue=clr.b;}if(red>1||green>1||blue>1){red/=255;green/=255;blue/=255;}var max=mmax(red,green,blue),min=mmin(red,green,blue),h,s,l=(max+min)/2,hsl;if(min==max){hsl={h:0,s:0,l:l};}else {var delta=max-min;s=l<.5?delta/(max+min):delta/(2-max-min);if(red==max){h=(green-blue)/delta;}else if(green==max){h=2+(blue-red)/delta;}else {h=4+(red-green)/delta;}h/=6;h<0&&h++;h>1&&h--;hsl={h:h,s:s,l:l};}hsl.toString=hsltoString;return hsl};R._path2string=function(){return this.join(",")[rp](p2s,"$1")};function cacher(f,scope,postprocessor){function newf(){var arg=Array[proto].slice.call(arguments,0),args=arg[join]("►"),cache=newf.cache=newf.cache||{},count=newf.count=newf.count||[];if(cache[has](args)){return postprocessor?postprocessor(cache[args]):cache[args]}count[length]>=1e3&&delete cache[count.shift()];count[push](args);cache[args]=f[apply](scope,arg);return postprocessor?postprocessor(cache[args]):cache[args]}return newf}R.getRGB=cacher(function(colour){if(!colour||!!((colour=Str(colour)).indexOf("-")+1)){return {r:-1,g:-1,b:-1,hex:"none",error:1}}if(colour=="none"){return {r:-1,g:-1,b:-1,hex:"none"}}!(hsrg[has](colour.toLowerCase().substring(0,2))||colour.charAt()=="#")&&(colour=toHex(colour));var red,green,blue,opacity,t,values,rgb=colour.match(colourRegExp);if(rgb){if(rgb[2]){blue=toInt(rgb[2].substring(5),16);green=toInt(rgb[2].substring(3,5),16);red=toInt(rgb[2].substring(1,3),16);}if(rgb[3]){blue=toInt((t=rgb[3].charAt(3))+t,16);green=toInt((t=rgb[3].charAt(2))+t,16);red=toInt((t=rgb[3].charAt(1))+t,16);}if(rgb[4]){values=rgb[4][split](commaSpaces);red=toFloat(values[0]);values[0].slice(-1)=="%"&&(red*=2.55);green=toFloat(values[1]);values[1].slice(-1)=="%"&&(green*=2.55);blue=toFloat(values[2]);values[2].slice(-1)=="%"&&(blue*=2.55);rgb[1].toLowerCase().slice(0,4)=="rgba"&&(opacity=toFloat(values[3]));values[3]&&values[3].slice(-1)=="%"&&(opacity/=100);}if(rgb[5]){values=rgb[5][split](commaSpaces);red=toFloat(values[0]);values[0].slice(-1)=="%"&&(red*=2.55);green=toFloat(values[1]);values[1].slice(-1)=="%"&&(green*=2.55);blue=toFloat(values[2]);values[2].slice(-1)=="%"&&(blue*=2.55);(values[0].slice(-3)=="deg"||values[0].slice(-1)=="°")&&(red/=360);rgb[1].toLowerCase().slice(0,4)=="hsba"&&(opacity=toFloat(values[3]));values[3]&&values[3].slice(-1)=="%"&&(opacity/=100);return R.hsb2rgb(red,green,blue,opacity)}if(rgb[6]){values=rgb[6][split](commaSpaces);red=toFloat(values[0]);values[0].slice(-1)=="%"&&(red*=2.55);green=toFloat(values[1]);values[1].slice(-1)=="%"&&(green*=2.55);blue=toFloat(values[2]);values[2].slice(-1)=="%"&&(blue*=2.55);(values[0].slice(-3)=="deg"||values[0].slice(-1)=="°")&&(red/=360);rgb[1].toLowerCase().slice(0,4)=="hsla"&&(opacity=toFloat(values[3]));values[3]&&values[3].slice(-1)=="%"&&(opacity/=100);return R.hsl2rgb(red,green,blue,opacity)}rgb={r:red,g:green,b:blue};rgb.hex="#"+(0x1000000|blue|green<<8|red<<16).toString(16).slice(1);R.is(opacity,"finite")&&(rgb.opacity=opacity);return rgb}return {r:-1,g:-1,b:-1,hex:"none",error:1}},R);R.getColor=function(value){var start=this.getColor.start=this.getColor.start||{h:0,s:1,b:value||.75},rgb=this.hsb2rgb(start.h,start.s,start.b);start.h+=.075;if(start.h>1){start.h=0;start.s-=.2;start.s<=0&&(this.getColor.start={h:0,s:1,b:start.b});}return rgb.hex};R.getColor.reset=function(){delete this.start;};R.parsePathString=cacher(function(pathString){if(!pathString){return null}var paramCounts={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},data=[];if(R.is(pathString,array)&&R.is(pathString[0],array)){data=pathClone(pathString);}if(!data[length]){Str(pathString)[rp](pathCommand,function(a,b,c){var params=[],name=lowerCase.call(b);c[rp](pathValues,function(a,b){b&&params[push](+b);});if(name=="m"&&params[length]>2){data[push]([b][concat](params.splice(0,2)));name="l";b=b=="m"?"l":"L";}while(params[length]>=paramCounts[name]){data[push]([b][concat](params.splice(0,paramCounts[name])));if(!paramCounts[name]){break}}});}data[toString]=R._path2string;return data});R.findDotsAtSegment=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t){var t1=1-t,x=pow(t1,3)*p1x+pow(t1,2)*3*t*c1x+t1*3*t*t*c2x+pow(t,3)*p2x,y=pow(t1,3)*p1y+pow(t1,2)*3*t*c1y+t1*3*t*t*c2y+pow(t,3)*p2y,mx=p1x+2*t*(c1x-p1x)+t*t*(c2x-2*c1x+p1x),my=p1y+2*t*(c1y-p1y)+t*t*(c2y-2*c1y+p1y),nx=c1x+2*t*(c2x-c1x)+t*t*(p2x-2*c2x+c1x),ny=c1y+2*t*(c2y-c1y)+t*t*(p2y-2*c2y+c1y),ax=(1-t)*p1x+t*c1x,ay=(1-t)*p1y+t*c1y,cx=(1-t)*c2x+t*p2x,cy=(1-t)*c2y+t*p2y,alpha=90-math.atan((mx-nx)/(my-ny))*180/PI;(mx>nx||my<ny)&&(alpha+=180);return {x:x,y:y,m:{x:mx,y:my},n:{x:nx,y:ny},start:{x:ax,y:ay},end:{x:cx,y:cy},alpha:alpha}};var pathDimensions=cacher(function(path){if(!path){return {x:0,y:0,width:0,height:0}}path=path2curve(path);var x=0,y=0,X=[],Y=[],p;for(var i=0,ii1=path[length];i<ii1;i++){p=path[i];if(p[0]=="M"){x=p[1];y=p[2];X[push](x);Y[push](y);}else {var dim=curveDim(x,y,p[1],p[2],p[3],p[4],p[5],p[6]);X=X[concat](dim.min.x,dim.max.x);Y=Y[concat](dim.min.y,dim.max.y);x=p[5];y=p[6];}}var xmin=mmin[apply](0,X),ymin=mmin[apply](0,Y);return {x:xmin,y:ymin,width:mmax[apply](0,X)-xmin,height:mmax[apply](0,Y)-ymin}}),pathClone=function(pathArray){var res=[];if(!R.is(pathArray,array)||!R.is(pathArray&&pathArray[0],array)){pathArray=R.parsePathString(pathArray);}for(var i=0,ii1=pathArray[length];i<ii1;i++){res[i]=[];for(var j=0,jj=pathArray[i][length];j<jj;j++){res[i][j]=pathArray[i][j];}}res[toString]=R._path2string;return res},pathToRelative=cacher(function(pathArray){if(!R.is(pathArray,array)||!R.is(pathArray&&pathArray[0],array)){pathArray=R.parsePathString(pathArray);}var res=[],x=0,y=0,mx=0,my=0,start=0;if(pathArray[0][0]=="M"){x=pathArray[0][1];y=pathArray[0][2];mx=x;my=y;start++;res[push](["M",x,y]);}for(var i=start,ii1=pathArray[length];i<ii1;i++){var r=res[i]=[],pa=pathArray[i];if(pa[0]!=lowerCase.call(pa[0])){r[0]=lowerCase.call(pa[0]);switch(r[0]){case "a":r[1]=pa[1];r[2]=pa[2];r[3]=pa[3];r[4]=pa[4];r[5]=pa[5];r[6]=+(pa[6]-x).toFixed(3);r[7]=+(pa[7]-y).toFixed(3);break;case "v":r[1]=+(pa[1]-y).toFixed(3);break;case "m":mx=pa[1];my=pa[2];default:for(var j=1,jj=pa[length];j<jj;j++){r[j]=+(pa[j]-(j%2?x:y)).toFixed(3);}}}else {r=res[i]=[];if(pa[0]=="m"){mx=pa[1]+x;my=pa[2]+y;}for(var k=0,kk=pa[length];k<kk;k++){res[i][k]=pa[k];}}var len=res[i][length];switch(res[i][0]){case "z":x=mx;y=my;break;case "h":x+=+res[i][len-1];break;case "v":y+=+res[i][len-1];break;default:x+=+res[i][len-2];y+=+res[i][len-1];}}res[toString]=R._path2string;return res},0,pathClone),pathToAbsolute=cacher(function(pathArray){if(!R.is(pathArray,array)||!R.is(pathArray&&pathArray[0],array)){pathArray=R.parsePathString(pathArray);}var res=[],x=0,y=0,mx=0,my=0,start=0;if(pathArray[0][0]=="M"){x=+pathArray[0][1];y=+pathArray[0][2];mx=x;my=y;start++;res[0]=["M",x,y];}for(var i=start,ii1=pathArray[length];i<ii1;i++){var r=res[i]=[],pa=pathArray[i];if(pa[0]!=upperCase.call(pa[0])){r[0]=upperCase.call(pa[0]);switch(r[0]){case "A":r[1]=pa[1];r[2]=pa[2];r[3]=pa[3];r[4]=pa[4];r[5]=pa[5];r[6]=+(pa[6]+x);r[7]=+(pa[7]+y);break;case "V":r[1]=+pa[1]+y;break;case "H":r[1]=+pa[1]+x;break;case "M":mx=+pa[1]+x;my=+pa[2]+y;default:for(var j=1,jj=pa[length];j<jj;j++){r[j]=+pa[j]+(j%2?x:y);}}}else {for(var k=0,kk=pa[length];k<kk;k++){res[i][k]=pa[k];}}switch(r[0]){case "Z":x=mx;y=my;break;case "H":x=r[1];break;case "V":y=r[1];break;case "M":mx=res[i][res[i][length]-2];my=res[i][res[i][length]-1];default:x=res[i][res[i][length]-2];y=res[i][res[i][length]-1];}}res[toString]=R._path2string;return res},null,pathClone),l2c=function(x1,y1,x2,y2){return [x1,y1,x2,y2,x2,y2]},q2c=function(x1,y1,ax,ay,x2,y2){var _13=1/3,_23=2/3;return [_13*x1+_23*ax,_13*y1+_23*ay,_13*x2+_23*ax,_13*y2+_23*ay,x2,y2]},a2c=function(x1,y1,rx,ry,angle,large_arc_flag,sweep_flag,x2,y2,recursive){var _120=PI*120/180,rad=PI/180*(+angle||0),res=[],xy,rotate=cacher(function(x,y,rad){var X=x*math.cos(rad)-y*math.sin(rad),Y=x*math.sin(rad)+y*math.cos(rad);return {x:X,y:Y}});if(!recursive){xy=rotate(x1,y1,-rad);x1=xy.x;y1=xy.y;xy=rotate(x2,y2,-rad);x2=xy.x;y2=xy.y;var x=(x1-x2)/2,y=(y1-y2)/2;var h=x*x/(rx*rx)+y*y/(ry*ry);if(h>1){h=math.sqrt(h);rx=h*rx;ry=h*ry;}var rx2=rx*rx,ry2=ry*ry,k=(large_arc_flag==sweep_flag?-1:1)*math.sqrt(abs((rx2*ry2-rx2*y*y-ry2*x*x)/(rx2*y*y+ry2*x*x))),cx=k*rx*y/ry+(x1+x2)/2,cy=k*-ry*x/rx+(y1+y2)/2,f1=math.asin(((y1-cy)/ry).toFixed(9)),f2=math.asin(((y2-cy)/ry).toFixed(9));f1=x1<cx?PI-f1:f1;f2=x2<cx?PI-f2:f2;f1<0&&(f1=PI*2+f1);f2<0&&(f2=PI*2+f2);if(sweep_flag&&f1>f2){f1=f1-PI*2;}if(!sweep_flag&&f2>f1){f2=f2-PI*2;}}else {f1=recursive[0];f2=recursive[1];cx=recursive[2];cy=recursive[3];}var df=f2-f1;if(abs(df)>_120){var f2old=f2,x2old=x2,y2old=y2;f2=f1+_120*(sweep_flag&&f2>f1?1:-1);x2=cx+rx*math.cos(f2);y2=cy+ry*math.sin(f2);res=a2c(x2,y2,rx,ry,angle,0,sweep_flag,x2old,y2old,[f2,f2old,cx,cy]);}df=f2-f1;var c1=math.cos(f1),s1=math.sin(f1),c2=math.cos(f2),s2=math.sin(f2),t=math.tan(df/4),hx=4/3*rx*t,hy=4/3*ry*t,m1=[x1,y1],m2=[x1+hx*s1,y1-hy*c1],m3=[x2+hx*s2,y2-hy*c2],m4=[x2,y2];m2[0]=2*m1[0]-m2[0];m2[1]=2*m1[1]-m2[1];if(recursive){return [m2,m3,m4][concat](res)}else {res=[m2,m3,m4][concat](res)[join]()[split](",");var newres=[];for(var i=0,ii1=res[length];i<ii1;i++){newres[i]=i%2?rotate(res[i-1],res[i],rad).y:rotate(res[i],res[i+1],rad).x;}return newres}},findDotAtSegment=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t){var t1=1-t;return {x:pow(t1,3)*p1x+pow(t1,2)*3*t*c1x+t1*3*t*t*c2x+pow(t,3)*p2x,y:pow(t1,3)*p1y+pow(t1,2)*3*t*c1y+t1*3*t*t*c2y+pow(t,3)*p2y}},curveDim=cacher(function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y){var a=c2x-2*c1x+p1x-(p2x-2*c2x+c1x),b=2*(c1x-p1x)-2*(c2x-c1x),c=p1x-c1x,t1=(-b+math.sqrt(b*b-4*a*c))/2/a,t2=(-b-math.sqrt(b*b-4*a*c))/2/a,y=[p1y,p2y],x=[p1x,p2x],dot;abs(t1)>"1e12"&&(t1=.5);abs(t2)>"1e12"&&(t2=.5);if(t1>0&&t1<1){dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t1);x[push](dot.x);y[push](dot.y);}if(t2>0&&t2<1){dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t2);x[push](dot.x);y[push](dot.y);}a=c2y-2*c1y+p1y-(p2y-2*c2y+c1y);b=2*(c1y-p1y)-2*(c2y-c1y);c=p1y-c1y;t1=(-b+math.sqrt(b*b-4*a*c))/2/a;t2=(-b-math.sqrt(b*b-4*a*c))/2/a;abs(t1)>"1e12"&&(t1=.5);abs(t2)>"1e12"&&(t2=.5);if(t1>0&&t1<1){dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t1);x[push](dot.x);y[push](dot.y);}if(t2>0&&t2<1){dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t2);x[push](dot.x);y[push](dot.y);}return {min:{x:mmin[apply](0,x),y:mmin[apply](0,y)},max:{x:mmax[apply](0,x),y:mmax[apply](0,y)}}}),path2curve=cacher(function(path,path2){var p=pathToAbsolute(path),p2=path2&&pathToAbsolute(path2),attrs={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},attrs2={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},processPath=function(path,d){var nx,ny;if(!path){return ["C",d.x,d.y,d.x,d.y,d.x,d.y]}!(path[0]in{T:1,Q:1})&&(d.qx=d.qy=null);switch(path[0]){case "M":d.X=path[1];d.Y=path[2];break;case "A":path=["C"][concat](a2c[apply](0,[d.x,d.y][concat](path.slice(1))));break;case "S":nx=d.x+(d.x-(d.bx||d.x));ny=d.y+(d.y-(d.by||d.y));path=["C",nx,ny][concat](path.slice(1));break;case "T":d.qx=d.x+(d.x-(d.qx||d.x));d.qy=d.y+(d.y-(d.qy||d.y));path=["C"][concat](q2c(d.x,d.y,d.qx,d.qy,path[1],path[2]));break;case "Q":d.qx=path[1];d.qy=path[2];path=["C"][concat](q2c(d.x,d.y,path[1],path[2],path[3],path[4]));break;case "L":path=["C"][concat](l2c(d.x,d.y,path[1],path[2]));break;case "H":path=["C"][concat](l2c(d.x,d.y,path[1],d.y));break;case "V":path=["C"][concat](l2c(d.x,d.y,d.x,path[1]));break;case "Z":path=["C"][concat](l2c(d.x,d.y,d.X,d.Y));break}return path},fixArc=function(pp,i){if(pp[i][length]>7){pp[i].shift();var pi=pp[i];while(pi[length]){pp.splice(i++,0,["C"][concat](pi.splice(0,6)));}pp.splice(i,1);ii1=mmax(p[length],p2&&p2[length]||0);}},fixM=function(path1,path2,a1,a2,i){if(path1&&path2&&path1[i][0]=="M"&&path2[i][0]!="M"){path2.splice(i,0,["M",a2.x,a2.y]);a1.bx=0;a1.by=0;a1.x=path1[i][1];a1.y=path1[i][2];ii1=mmax(p[length],p2&&p2[length]||0);}};for(var i=0,ii1=mmax(p[length],p2&&p2[length]||0);i<ii1;i++){p[i]=processPath(p[i],attrs);fixArc(p,i);p2&&(p2[i]=processPath(p2[i],attrs2));p2&&fixArc(p2,i);fixM(p,p2,attrs,attrs2,i);fixM(p2,p,attrs2,attrs,i);var seg=p[i],seg2=p2&&p2[i],seglen=seg[length],seg2len=p2&&seg2[length];attrs.x=seg[seglen-2];attrs.y=seg[seglen-1];attrs.bx=toFloat(seg[seglen-4])||attrs.x;attrs.by=toFloat(seg[seglen-3])||attrs.y;attrs2.bx=p2&&(toFloat(seg2[seg2len-4])||attrs2.x);attrs2.by=p2&&(toFloat(seg2[seg2len-3])||attrs2.y);attrs2.x=p2&&seg2[seg2len-2];attrs2.y=p2&&seg2[seg2len-1];}return p2?[p,p2]:p},null,pathClone),parseDots=cacher(function(gradient){var dots=[];for(var i=0,ii1=gradient[length];i<ii1;i++){var dot={},par=gradient[i].match(/^([^:]*):?([\d\.]*)/);dot.color=R.getRGB(par[1]);if(dot.color.error){return null}dot.color=dot.color.hex;par[2]&&(dot.offset=par[2]+"%");dots[push](dot);}for(i=1,ii1=dots[length]-1;i<ii1;i++){if(!dots[i].offset){var start=toFloat(dots[i-1].offset||0),end=0;for(var j=i+1;j<ii1;j++){if(dots[j].offset){end=dots[j].offset;break}}if(!end){end=100;j=ii1;}end=toFloat(end);var d=(end-start)/(j-i+1);for(;i<j;i++){start+=d;dots[i].offset=start+"%";}}}return dots}),getContainer=function(x,y,w,h){var container;if(R.is(x,string)||R.is(x,"object")){container=R.is(x,string)?doc.getElementById(x):x;if(container.tagName){if(y==null){return {container:container,width:container.style.pixelWidth||container.offsetWidth,height:container.style.pixelHeight||container.offsetHeight}}else {return {container:container,width:y,height:w}}}}else {return {container:1,x:x,y:y,width:w,height:h}}},plugins=function(con,add){var that=this;for(var prop in add){if(add[has](prop)&&!(prop in con)){switch(typeof add[prop]){case "function":(function(f){con[prop]=con===that?f:function(){return f[apply](that,arguments)};})(add[prop]);break;case "object":con[prop]=con[prop]||{};plugins.call(this,con[prop],add[prop]);break;default:con[prop]=add[prop];break}}}},tear=function(el,paper){el==paper.top&&(paper.top=el.prev);el==paper.bottom&&(paper.bottom=el.next);el.next&&(el.next.prev=el.prev);el.prev&&(el.prev.next=el.next);},tofront=function(el,paper){if(paper.top===el){return}tear(el,paper);el.next=null;el.prev=paper.top;paper.top.next=el;paper.top=el;},toback=function(el,paper){if(paper.bottom===el){return}tear(el,paper);el.next=paper.bottom;el.prev=null;paper.bottom.prev=el;paper.bottom=el;},insertafter=function(el,el2,paper){tear(el,paper);el2==paper.top&&(paper.top=el);el2.next&&(el2.next.prev=el);el.next=el2.next;el.prev=el2;el2.next=el;},insertbefore=function(el,el2,paper){tear(el,paper);el2==paper.bottom&&(paper.bottom=el);el2.prev&&(el2.prev.next=el);el.prev=el2.prev;el2.prev=el;el.next=el2;},removed=function(methodname){return function(){throw new Error("Raphaël: you are calling to method “"+methodname+"” of removed object")}};R.pathToRelative=pathToRelative;if(R.svg){paperproto.svgns="http://www.w3.org/2000/svg";paperproto.xlink="http://www.w3.org/1999/xlink";round=function(num){return +num+(~~num===num)*.5};var $=function(el,attr){if(attr){for(var key in attr){if(attr[has](key)){setAttr(el,key,Str(attr[key]));}}}else {el=doc.createElementNS(paperproto.svgns,el);el.style.webkitTapHighlightColor="rgba(0,0,0,0)";return el}};R[toString]=function(){return "Your browser supports SVG.\nYou are running Raphaël "+this.version};var thePath=function(pathString,SVG){var el=$("path");SVG.canvas&&SVG.canvas[appendChild](el);var p=new Element(el,SVG);p.type="path";setFillAndStroke(p,{fill:"none",stroke:"#000",path:pathString});return p};var addGradientFill=function(o,gradient,SVG){var type="linear",fx=.5,fy=.5,s=o.style;gradient=Str(gradient)[rp](radial_gradient,function(all,_fx,_fy){type="radial";if(_fx&&_fy){fx=toFloat(_fx);fy=toFloat(_fy);var dir=(fy>.5)*2-1;pow(fx-.5,2)+pow(fy-.5,2)>.25&&(fy=math.sqrt(.25-pow(fx-.5,2))*dir+.5)&&fy!=.5&&(fy=fy.toFixed(5)-1e-5*dir);}return E});gradient=gradient[split](/\s*\-\s*/);if(type=="linear"){var angle=gradient.shift();angle=-toFloat(angle);if(isNaN(angle)){return null}var vector=[0,0,math.cos(angle*PI/180),math.sin(angle*PI/180)],max=1/(mmax(abs(vector[2]),abs(vector[3]))||1);vector[2]*=max;vector[3]*=max;if(vector[2]<0){vector[0]=-vector[2];vector[2]=0;}if(vector[3]<0){vector[1]=-vector[3];vector[3]=0;}}var dots=parseDots(gradient);if(!dots){return null}var id=o.getAttribute(fillString);id=id.match(/^url\(#(.*)\)$/);id&&SVG.defs.removeChild(doc.getElementById(id[1]));var el=$(type+"Gradient");el.id=createUUID();$(el,type=="radial"?{fx:fx,fy:fy}:{x1:vector[0],y1:vector[1],x2:vector[2],y2:vector[3]});SVG.defs[appendChild](el);for(var i=0,ii1=dots[length];i<ii1;i++){var stop=$("stop");$(stop,{offset:dots[i].offset?dots[i].offset:!i?"0%":"100%","stop-color":dots[i].color||"#fff"});el[appendChild](stop);}$(o,{fill:"url(#"+el.id+")",opacity:1,"fill-opacity":1});s.fill=E;s.opacity=1;s.fillOpacity=1;return 1};var updatePosition=function(o){var bbox=o.getBBox();$(o.pattern,{patternTransform:R.format("translate({0},{1})",bbox.x,bbox.y)});};var setFillAndStroke=function(o,params){var dasharray={"":[0],"none":[0],"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},node=o.node,attrs=o.attrs,rot=o.rotate(),addDashes=function(o,value){value=dasharray[lowerCase.call(value)];if(value){var width=o.attrs["stroke-width"]||"1",butt={round:width,square:width,butt:0}[o.attrs["stroke-linecap"]||params["stroke-linecap"]]||0,dashes=[];var i=value[length];while(i--){dashes[i]=value[i]*width+(i%2?1:-1)*butt;}$(node,{"stroke-dasharray":dashes[join](",")});}};params[has]("rotation")&&(rot=params.rotation);var rotxy=Str(rot)[split](separator);if(!(rotxy.length-1)){rotxy=null;}else {rotxy[1]=+rotxy[1];rotxy[2]=+rotxy[2];}toFloat(rot)&&o.rotate(0,true);for(var att in params){if(params[has](att)){if(!availableAttrs[has](att)){continue}var value=params[att];attrs[att]=value;switch(att){case "blur":o.blur(value);break;case "rotation":o.rotate(value,true);break;case "href":case "title":case "target":var pn=node.parentNode;if(lowerCase.call(pn.tagName)!="a"){var hl=$("a");pn.insertBefore(hl,node);hl[appendChild](node);pn=hl;}if(att=="target"&&value=="blank"){pn.setAttributeNS(o.paper.xlink,"show","new");}else {pn.setAttributeNS(o.paper.xlink,att,value);}break;case "cursor":node.style.cursor=value;break;case "clip-rect":var rect=Str(value)[split](separator);if(rect[length]==4){o.clip&&o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);var el=$("clipPath"),rc=$("rect");el.id=createUUID();$(rc,{x:rect[0],y:rect[1],width:rect[2],height:rect[3]});el[appendChild](rc);o.paper.defs[appendChild](el);$(node,{"clip-path":"url(#"+el.id+")"});o.clip=rc;}if(!value){var clip=doc.getElementById(node.getAttribute("clip-path")[rp](/(^url\(#|\)$)/g,E));clip&&clip.parentNode.removeChild(clip);$(node,{"clip-path":E});delete o.clip;}break;case "path":if(o.type=="path"){$(node,{d:value?attrs.path=pathToAbsolute(value):"M0,0"});}break;case "width":setAttr(node,att,value);if(attrs.fx){att="x";value=attrs.x;}else {break}case "x":if(attrs.fx){value=-attrs.x-(attrs.width||0);}case "rx":if(att=="rx"&&o.type=="rect"){break}case "cx":rotxy&&(att=="x"||att=="cx")&&(rotxy[1]+=value-attrs[att]);setAttr(node,att,value);o.pattern&&updatePosition(o);break;case "height":setAttr(node,att,value);if(attrs.fy){att="y";value=attrs.y;}else {break}case "y":if(attrs.fy){value=-attrs.y-(attrs.height||0);}case "ry":if(att=="ry"&&o.type=="rect"){break}case "cy":rotxy&&(att=="y"||att=="cy")&&(rotxy[2]+=value-attrs[att]);setAttr(node,att,value);o.pattern&&updatePosition(o);break;case "r":if(o.type=="rect"){$(node,{rx:value,ry:value});}else {setAttr(node,att,value);}break;case "src":if(o.type=="image"){node.setAttributeNS(o.paper.xlink,"href",value);}break;case "stroke-width":node.style.strokeWidth=value;setAttr(node,att,value);if(attrs["stroke-dasharray"]){addDashes(o,attrs["stroke-dasharray"]);}break;case "stroke-dasharray":addDashes(o,value);break;case "translation":var xy=Str(value)[split](separator);xy[0]=+xy[0]||0;xy[1]=+xy[1]||0;if(rotxy){rotxy[1]+=xy[0];rotxy[2]+=xy[1];}translate.call(o,xy[0],xy[1]);break;case "scale":xy=Str(value)[split](separator);o.scale(+xy[0]||1,+xy[1]||+xy[0]||1,isNaN(toFloat(xy[2]))?null:+xy[2],isNaN(toFloat(xy[3]))?null:+xy[3]);break;case fillString:var isURL=Str(value).match(ISURL);if(isURL){el=$("pattern");var ig=$("image");el.id=createUUID();$(el,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1});$(ig,{x:0,y:0});ig.setAttributeNS(o.paper.xlink,"href",isURL[1]);el[appendChild](ig);var img=doc.createElement("img");img.style.cssText="position:absolute;left:-9999em;top-9999em";img.onload=function(){$(el,{width:this.offsetWidth,height:this.offsetHeight});$(ig,{width:this.offsetWidth,height:this.offsetHeight});doc.body.removeChild(this);o.paper.safari();};doc.body[appendChild](img);img.src=isURL[1];o.paper.defs[appendChild](el);node.style.fill="url(#"+el.id+")";$(node,{fill:"url(#"+el.id+")"});o.pattern=el;o.pattern&&updatePosition(o);break}var clr=R.getRGB(value);if(!clr.error){delete params.gradient;delete attrs.gradient;!R.is(attrs.opacity,"undefined")&&R.is(params.opacity,"undefined")&&$(node,{opacity:attrs.opacity});!R.is(attrs["fill-opacity"],"undefined")&&R.is(params["fill-opacity"],"undefined")&&$(node,{"fill-opacity":attrs["fill-opacity"]});}else if((({circle:1,ellipse:1})[has](o.type)||Str(value).charAt()!="r")&&addGradientFill(node,value,o.paper)){attrs.gradient=value;attrs.fill="none";break}clr[has]("opacity")&&$(node,{"fill-opacity":clr.opacity>1?clr.opacity/100:clr.opacity});case "stroke":clr=R.getRGB(value);setAttr(node,att,clr.hex);att=="stroke"&&clr[has]("opacity")&&$(node,{"stroke-opacity":clr.opacity>1?clr.opacity/100:clr.opacity});break;case "gradient":(({circle:1,ellipse:1})[has](o.type)||Str(value).charAt()!="r")&&addGradientFill(node,value,o.paper);break;case "opacity":if(attrs.gradient&&!attrs[has]("stroke-opacity")){$(node,{"stroke-opacity":value>1?value/100:value});}case "fill-opacity":if(attrs.gradient){var gradient=doc.getElementById(node.getAttribute(fillString)[rp](/^url\(#|\)$/g,E));if(gradient){var stops=gradient.getElementsByTagName("stop");setAttr(stops[stops[length]-1],"stop-opacity",value);}break}default:att=="font-size"&&(value=toInt(value,10)+"px");var cssrule=att[rp](/(\-.)/g,function(w){return upperCase.call(w.substring(1))});node.style[cssrule]=value;setAttr(node,att,value);break}}}tuneText(o,params);if(rotxy){o.rotate(rotxy.join(S));}else {toFloat(rot)&&o.rotate(rot,true);}};var leading=1.2,tuneText=function(el,params){if(el.type!="text"||!(params[has]("text")||params[has]("font")||params[has]("font-size")||params[has]("x")||params[has]("y"))){return}var a=el.attrs,node=el.node,fontSize=node.firstChild?toInt(doc.defaultView.getComputedStyle(node.firstChild,E).getPropertyValue("font-size"),10):10;if(params[has]("text")){a.text=params.text;while(node.firstChild){node.removeChild(node.firstChild);}var texts=Str(params.text)[split]("\n");for(var i=0,ii1=texts[length];i<ii1;i++)if(texts[i]){var tspan=$("tspan");i&&$(tspan,{dy:fontSize*leading,x:a.x});tspan[appendChild](doc.createTextNode(texts[i]));node[appendChild](tspan);}}else {texts=node.getElementsByTagName("tspan");for(i=0,ii1=texts[length];i<ii1;i++){i&&$(texts[i],{dy:fontSize*leading,x:a.x});}}$(node,{y:a.y});var bb=el.getBBox(),dif=a.y-(bb.y+bb.height/2);dif&&R.is(dif,"finite")&&$(node,{y:a.y+dif});},Element=function(node,svg){this[0]=node;this.id=R._oid++;this.node=node;node.raphael=this;this.paper=svg;this.attrs=this.attrs||{};this.transformations=[];this._={tx:0,ty:0,rt:{deg:0,cx:0,cy:0},sx:1,sy:1};!svg.bottom&&(svg.bottom=this);this.prev=svg.top;svg.top&&(svg.top.next=this);svg.top=this;this.next=null;};var elproto=Element[proto];Element[proto].rotate=function(deg,cx,cy){if(this.removed){return this}if(deg==null){if(this._.rt.cx){return [this._.rt.deg,this._.rt.cx,this._.rt.cy][join](S)}return this._.rt.deg}var bbox=this.getBBox();deg=Str(deg)[split](separator);if(deg[length]-1){cx=toFloat(deg[1]);cy=toFloat(deg[2]);}deg=toFloat(deg[0]);if(cx!=null&&cx!==false){this._.rt.deg=deg;}else {this._.rt.deg+=deg;}cy==null&&(cx=null);this._.rt.cx=cx;this._.rt.cy=cy;cx=cx==null?bbox.x+bbox.width/2:cx;cy=cy==null?bbox.y+bbox.height/2:cy;if(this._.rt.deg){this.transformations[0]=R.format("rotate({0} {1} {2})",this._.rt.deg,cx,cy);this.clip&&$(this.clip,{transform:R.format("rotate({0} {1} {2})",-this._.rt.deg,cx,cy)});}else {this.transformations[0]=E;this.clip&&$(this.clip,{transform:E});}$(this.node,{transform:this.transformations[join](S)});return this};Element[proto].hide=function(){!this.removed&&(this.node.style.display="none");return this};Element[proto].show=function(){!this.removed&&(this.node.style.display="");return this};Element[proto].remove=function(){if(this.removed){return}tear(this,this.paper);this.node.parentNode.removeChild(this.node);for(var i in this){delete this[i];}this.removed=true;};Element[proto].getBBox=function(){if(this.removed){return this}if(this.type=="path"){return pathDimensions(this.attrs.path)}if(this.node.style.display=="none"){this.show();var hide=true;}var bbox={};try{bbox=this.node.getBBox();}catch(e){}finally{bbox=bbox||{};}if(this.type=="text"){bbox={x:bbox.x,y:Infinity,width:0,height:0};for(var i=0,ii1=this.node.getNumberOfChars();i<ii1;i++){var bb=this.node.getExtentOfChar(i);bb.y<bbox.y&&(bbox.y=bb.y);bb.y+bb.height-bbox.y>bbox.height&&(bbox.height=bb.y+bb.height-bbox.y);bb.x+bb.width-bbox.x>bbox.width&&(bbox.width=bb.x+bb.width-bbox.x);}}hide&&this.hide();return bbox};Element[proto].attr=function(name,value){if(this.removed){return this}if(name==null){var res={};for(var i in this.attrs)if(this.attrs[has](i)){res[i]=this.attrs[i];}this._.rt.deg&&(res.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(res.scale=this.scale());res.gradient&&res.fill=="none"&&(res.fill=res.gradient)&&delete res.gradient;return res}if(value==null&&R.is(name,string)){if(name=="translation"){return translate.call(this)}if(name=="rotation"){return this.rotate()}if(name=="scale"){return this.scale()}if(name==fillString&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient}return this.attrs[name]}if(value==null&&R.is(name,array)){var values={};for(var j=0,jj=name.length;j<jj;j++){values[name[j]]=this.attr(name[j]);}return values}if(value!=null){var params={};params[name]=value;}else if(name!=null&&R.is(name,"object")){params=name;}for(var key in this.paper.customAttributes)if(this.paper.customAttributes[has](key)&&params[has](key)&&R.is(this.paper.customAttributes[key],"function")){var par=this.paper.customAttributes[key].apply(this,[][concat](params[key]));this.attrs[key]=params[key];for(var subkey in par)if(par[has](subkey)){params[subkey]=par[subkey];}}setFillAndStroke(this,params);return this};Element[proto].toFront=function(){if(this.removed){return this}this.node.parentNode[appendChild](this.node);var svg=this.paper;svg.top!=this&&tofront(this,svg);return this};Element[proto].toBack=function(){if(this.removed){return this}if(this.node.parentNode.firstChild!=this.node){this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild);toback(this,this.paper);this.paper;}return this};Element[proto].insertAfter=function(element){if(this.removed){return this}var node=element.node||element[element.length-1].node;if(node.nextSibling){node.parentNode.insertBefore(this.node,node.nextSibling);}else {node.parentNode[appendChild](this.node);}insertafter(this,element,this.paper);return this};Element[proto].insertBefore=function(element){if(this.removed){return this}var node=element.node||element[0].node;node.parentNode.insertBefore(this.node,node);insertbefore(this,element,this.paper);return this};Element[proto].blur=function(size){var t=this;if(+size!==0){var fltr=$("filter"),blur=$("feGaussianBlur");t.attrs.blur=size;fltr.id=createUUID();$(blur,{stdDeviation:+size||1.5});fltr.appendChild(blur);t.paper.defs.appendChild(fltr);t._blur=fltr;$(t.node,{filter:"url(#"+fltr.id+")"});}else {if(t._blur){t._blur.parentNode.removeChild(t._blur);delete t._blur;delete t.attrs.blur;}t.node.removeAttribute("filter");}};var theCircle=function(svg,x,y,r){var el=$("circle");svg.canvas&&svg.canvas[appendChild](el);var res=new Element(el,svg);res.attrs={cx:x,cy:y,r:r,fill:"none",stroke:"#000"};res.type="circle";$(el,res.attrs);return res},theRect=function(svg,x,y,w,h,r){var el=$("rect");svg.canvas&&svg.canvas[appendChild](el);var res=new Element(el,svg);res.attrs={x:x,y:y,width:w,height:h,r:r||0,rx:r||0,ry:r||0,fill:"none",stroke:"#000"};res.type="rect";$(el,res.attrs);return res},theEllipse=function(svg,x,y,rx,ry){var el=$("ellipse");svg.canvas&&svg.canvas[appendChild](el);var res=new Element(el,svg);res.attrs={cx:x,cy:y,rx:rx,ry:ry,fill:"none",stroke:"#000"};res.type="ellipse";$(el,res.attrs);return res},theImage=function(svg,src,x,y,w,h){var el=$("image");$(el,{x:x,y:y,width:w,height:h,preserveAspectRatio:"none"});el.setAttributeNS(svg.xlink,"href",src);svg.canvas&&svg.canvas[appendChild](el);var res=new Element(el,svg);res.attrs={x:x,y:y,width:w,height:h,src:src};res.type="image";return res},theText=function(svg,x,y,text){var el=$("text");$(el,{x:x,y:y,"text-anchor":"middle"});svg.canvas&&svg.canvas[appendChild](el);var res=new Element(el,svg);res.attrs={x:x,y:y,"text-anchor":"middle",text:text,font:availableAttrs.font,stroke:"none",fill:"#000"};res.type="text";setFillAndStroke(res,res.attrs);return res},setSize=function(width,height){this.width=width||this.width;this.height=height||this.height;setAttr(this.canvas,"width",this.width);setAttr(this.canvas,"height",this.height);return this},create=function(){var con=getContainer[apply](0,arguments),container=con&&con.container,x=con.x,y=con.y,width=con.width,height=con.height;if(!container){throw new Error("SVG container not found.")}var cnvs=$("svg");x=x||0;y=y||0;width=width||512;height=height||342;$(cnvs,{xmlns:"http://www.w3.org/2000/svg",version:1.1,width:width,height:height});if(container==1){cnvs.style.cssText="position:absolute;left:"+x+"px;top:"+y+"px";doc.body[appendChild](cnvs);}else {if(container.firstChild){container.insertBefore(cnvs,container.firstChild);}else {container[appendChild](cnvs);}}container=new Paper;container.width=width;container.height=height;container.canvas=cnvs;plugins.call(container,container,R.fn);container.clear();return container};paperproto.clear=function(){var c=this.canvas;while(c.firstChild){c.removeChild(c.firstChild);}this.bottom=this.top=null;(this.desc=$("desc"))[appendChild](doc.createTextNode("Created with Raphaël"));c[appendChild](this.desc);c[appendChild](this.defs=$("defs"));};paperproto.remove=function(){this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var i in this){this[i]=removed(i);}};}if(R.vml){var map={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},bites=/([clmz]),?([^clmz]*)/gi,blurregexp=/ progid:\S+Blur\([^\)]+\)/g,val=/-?[^,\s-]+/g,coordsize=1e3+S+1e3,zoom=10,pathlike={path:1,rect:1},path2vml=function(path){var total=/[ahqstv]/ig,command=pathToAbsolute;Str(path).match(total)&&(command=path2curve);total=/[clmz]/g;if(command==pathToAbsolute&&!Str(path).match(total)){var res=Str(path)[rp](bites,function(all,command,args){var vals=[],isMove=lowerCase.call(command)=="m",res=map[command];args[rp](val,function(value){if(isMove&&vals[length]==2){res+=vals+map[command=="m"?"l":"L"];vals=[];}vals[push](round(value*zoom));});return res+vals});return res}var pa=command(path),p,r;res=[];for(var i=0,ii1=pa[length];i<ii1;i++){p=pa[i];r=lowerCase.call(pa[i][0]);r=="z"&&(r="x");for(var j=1,jj=p[length];j<jj;j++){r+=round(p[j]*zoom)+(j!=jj-1?",":E);}res[push](r);}return res[join](S)};R[toString]=function(){return "Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël "+this.version};thePath=function(pathString,vml){var g=createNode("group");g.style.cssText="position:absolute;left:0;top:0;width:"+vml.width+"px;height:"+vml.height+"px";g.coordsize=vml.coordsize;g.coordorigin=vml.coordorigin;var el=createNode("shape"),ol=el.style;ol.width=vml.width+"px";ol.height=vml.height+"px";el.coordsize=coordsize;el.coordorigin=vml.coordorigin;g[appendChild](el);var p=new Element(el,g,vml),attr={fill:"none",stroke:"#000"};pathString&&(attr.path=pathString);p.type="path";p.path=[];p.Path=E;setFillAndStroke(p,attr);vml.canvas[appendChild](g);return p};setFillAndStroke=function(o,params){o.attrs=o.attrs||{};var node=o.node,a=o.attrs,s=node.style,xy,newpath=(params.x!=a.x||params.y!=a.y||params.width!=a.width||params.height!=a.height||params.r!=a.r)&&o.type=="rect",res=o;for(var par in params)if(params[has](par)){a[par]=params[par];}if(newpath){a.path=rectPath(a.x,a.y,a.width,a.height,a.r);o.X=a.x;o.Y=a.y;o.W=a.width;o.H=a.height;}params.href&&(node.href=params.href);params.title&&(node.title=params.title);params.target&&(node.target=params.target);params.cursor&&(s.cursor=params.cursor);"blur"in params&&o.blur(params.blur);if(params.path&&o.type=="path"||newpath){node.path=path2vml(a.path);}if(params.rotation!=null){o.rotate(params.rotation,true);}if(params.translation){xy=Str(params.translation)[split](separator);translate.call(o,xy[0],xy[1]);if(o._.rt.cx!=null){o._.rt.cx+=+xy[0];o._.rt.cy+=+xy[1];o.setBox(o.attrs,xy[0],xy[1]);}}if(params.scale){xy=Str(params.scale)[split](separator);o.scale(+xy[0]||1,+xy[1]||+xy[0]||1,+xy[2]||null,+xy[3]||null);}if("clip-rect"in params){var rect=Str(params["clip-rect"])[split](separator);if(rect[length]==4){rect[2]=+rect[2]+ +rect[0];rect[3]=+rect[3]+ +rect[1];var div=node.clipRect||doc.createElement("div"),dstyle=div.style,group=node.parentNode;dstyle.clip=R.format("rect({1}px {2}px {3}px {0}px)",rect);if(!node.clipRect){dstyle.position="absolute";dstyle.top=0;dstyle.left=0;dstyle.width=o.paper.width+"px";dstyle.height=o.paper.height+"px";group.parentNode.insertBefore(div,group);div[appendChild](group);node.clipRect=div;}}if(!params["clip-rect"]){node.clipRect&&(node.clipRect.style.clip=E);}}if(o.type=="image"&&params.src){node.src=params.src;}if(o.type=="image"&&params.opacity){node.filterOpacity=ms+".Alpha(opacity="+params.opacity*100+")";s.filter=(node.filterMatrix||E)+(node.filterOpacity||E);}params.font&&(s.font=params.font);params["font-family"]&&(s.fontFamily='"'+params["font-family"][split](",")[0][rp](/^['"]+|['"]+$/g,E)+'"');params["font-size"]&&(s.fontSize=params["font-size"]);params["font-weight"]&&(s.fontWeight=params["font-weight"]);params["font-style"]&&(s.fontStyle=params["font-style"]);if(params.opacity!=null||params["stroke-width"]!=null||params.fill!=null||params.stroke!=null||params["stroke-width"]!=null||params["stroke-opacity"]!=null||params["fill-opacity"]!=null||params["stroke-dasharray"]!=null||params["stroke-miterlimit"]!=null||params["stroke-linejoin"]!=null||params["stroke-linecap"]!=null){node=o.shape||node;var fill=node.getElementsByTagName(fillString)&&node.getElementsByTagName(fillString)[0],newfill=false;!fill&&(newfill=fill=createNode(fillString));if("fill-opacity"in params||"opacity"in params){var opacity=((+a["fill-opacity"]+1||2)-1)*((+a.opacity+1||2)-1)*((+R.getRGB(params.fill).o+1||2)-1);opacity=mmin(mmax(opacity,0),1);fill.opacity=opacity;}params.fill&&(fill.on=true);if(fill.on==null||params.fill=="none"){fill.on=false;}if(fill.on&&params.fill){var isURL=params.fill.match(ISURL);if(isURL){fill.src=isURL[1];fill.type="tile";}else {fill.color=R.getRGB(params.fill).hex;fill.src=E;fill.type="solid";if(R.getRGB(params.fill).error&&(res.type in{circle:1,ellipse:1}||Str(params.fill).charAt()!="r")&&addGradientFill(res,params.fill)){a.fill="none";a.gradient=params.fill;}}}newfill&&node[appendChild](fill);var stroke=node.getElementsByTagName("stroke")&&node.getElementsByTagName("stroke")[0],newstroke=false;!stroke&&(newstroke=stroke=createNode("stroke"));if(params.stroke&&params.stroke!="none"||params["stroke-width"]||params["stroke-opacity"]!=null||params["stroke-dasharray"]||params["stroke-miterlimit"]||params["stroke-linejoin"]||params["stroke-linecap"]){stroke.on=true;}(params.stroke=="none"||stroke.on==null||params.stroke==0||params["stroke-width"]==0)&&(stroke.on=false);var strokeColor=R.getRGB(params.stroke);stroke.on&&params.stroke&&(stroke.color=strokeColor.hex);opacity=((+a["stroke-opacity"]+1||2)-1)*((+a.opacity+1||2)-1)*((+strokeColor.o+1||2)-1);var width=(toFloat(params["stroke-width"])||1)*.75;opacity=mmin(mmax(opacity,0),1);params["stroke-width"]==null&&(width=a["stroke-width"]);params["stroke-width"]&&(stroke.weight=width);width&&width<1&&(opacity*=width)&&(stroke.weight=1);stroke.opacity=opacity;params["stroke-linejoin"]&&(stroke.joinstyle=params["stroke-linejoin"]||"miter");stroke.miterlimit=params["stroke-miterlimit"]||8;params["stroke-linecap"]&&(stroke.endcap=params["stroke-linecap"]=="butt"?"flat":params["stroke-linecap"]=="square"?"square":"round");if(params["stroke-dasharray"]){var dasharray={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};stroke.dashstyle=dasharray[has](params["stroke-dasharray"])?dasharray[params["stroke-dasharray"]]:E;}newstroke&&node[appendChild](stroke);}if(res.type=="text"){s=res.paper.span.style;a.font&&(s.font=a.font);a["font-family"]&&(s.fontFamily=a["font-family"]);a["font-size"]&&(s.fontSize=a["font-size"]);a["font-weight"]&&(s.fontWeight=a["font-weight"]);a["font-style"]&&(s.fontStyle=a["font-style"]);res.node.string&&(res.paper.span.innerHTML=Str(res.node.string)[rp](/</g,"&#60;")[rp](/&/g,"&#38;")[rp](/\n/g,"<br>"));res.W=a.w=res.paper.span.offsetWidth;res.H=a.h=res.paper.span.offsetHeight;res.X=a.x;res.Y=a.y+round(res.H/2);switch(a["text-anchor"]){case "start":res.node.style["v-text-align"]="left";res.bbx=round(res.W/2);break;case "end":res.node.style["v-text-align"]="right";res.bbx=-round(res.W/2);break;default:res.node.style["v-text-align"]="center";break}}};addGradientFill=function(o,gradient){o.attrs=o.attrs||{};o.attrs;var fill,type="linear",fxfy=".5 .5";o.attrs.gradient=gradient;gradient=Str(gradient)[rp](radial_gradient,function(all,fx,fy){type="radial";if(fx&&fy){fx=toFloat(fx);fy=toFloat(fy);pow(fx-.5,2)+pow(fy-.5,2)>.25&&(fy=math.sqrt(.25-pow(fx-.5,2))*((fy>.5)*2-1)+.5);fxfy=fx+S+fy;}return E});gradient=gradient[split](/\s*\-\s*/);if(type=="linear"){var angle=gradient.shift();angle=-toFloat(angle);if(isNaN(angle)){return null}}var dots=parseDots(gradient);if(!dots){return null}o=o.shape||o.node;fill=o.getElementsByTagName(fillString)[0]||createNode(fillString);!fill.parentNode&&o.appendChild(fill);if(dots[length]){fill.on=true;fill.method="none";fill.color=dots[0].color;fill.color2=dots[dots[length]-1].color;var clrs=[];for(var i=0,ii1=dots[length];i<ii1;i++){dots[i].offset&&clrs[push](dots[i].offset+S+dots[i].color);}fill.colors&&(fill.colors.value=clrs[length]?clrs[join]():"0% "+fill.color);if(type=="radial"){fill.type="gradientradial";fill.focus="100%";fill.focussize=fxfy;fill.focusposition=fxfy;}else {fill.type="gradient";fill.angle=(270-angle)%360;}}return 1};Element=function(node,group,vml){this[0]=node;this.id=R._oid++;this.node=node;node.raphael=this;this.X=0;this.Y=0;this.attrs={};this.Group=group;this.paper=vml;this._={tx:0,ty:0,rt:{deg:0},sx:1,sy:1};!vml.bottom&&(vml.bottom=this);this.prev=vml.top;vml.top&&(vml.top.next=this);vml.top=this;this.next=null;};elproto=Element[proto];elproto.rotate=function(deg,cx,cy){if(this.removed){return this}if(deg==null){if(this._.rt.cx){return [this._.rt.deg,this._.rt.cx,this._.rt.cy][join](S)}return this._.rt.deg}deg=Str(deg)[split](separator);if(deg[length]-1){cx=toFloat(deg[1]);cy=toFloat(deg[2]);}deg=toFloat(deg[0]);if(cx!=null){this._.rt.deg=deg;}else {this._.rt.deg+=deg;}cy==null&&(cx=null);this._.rt.cx=cx;this._.rt.cy=cy;this.setBox(this.attrs,cx,cy);this.Group.style.rotation=this._.rt.deg;return this};elproto.setBox=function(params,cx,cy){if(this.removed){return this}var gs=this.Group.style,os=this.shape&&this.shape.style||this.node.style;params=params||{};for(var i in params)if(params[has](i)){this.attrs[i]=params[i];}cx=cx||this._.rt.cx;cy=cy||this._.rt.cy;var attr=this.attrs,x,y,w,h;switch(this.type){case "circle":x=attr.cx-attr.r;y=attr.cy-attr.r;w=h=attr.r*2;break;case "ellipse":x=attr.cx-attr.rx;y=attr.cy-attr.ry;w=attr.rx*2;h=attr.ry*2;break;case "image":x=+attr.x;y=+attr.y;w=attr.width||0;h=attr.height||0;break;case "text":this.textpath.v=["m",round(attr.x),", ",round(attr.y-2),"l",round(attr.x)+1,", ",round(attr.y-2)][join](E);x=attr.x-round(this.W/2);y=attr.y-this.H/2;w=this.W;h=this.H;break;case "rect":case "path":if(!this.attrs.path){x=0;y=0;w=this.paper.width;h=this.paper.height;}else {var dim=pathDimensions(this.attrs.path);x=dim.x;y=dim.y;w=dim.width;h=dim.height;}break;default:x=0;y=0;w=this.paper.width;h=this.paper.height;break}cx=cx==null?x+w/2:cx;cy=cy==null?y+h/2:cy;var left=cx-this.paper.width/2,top=cy-this.paper.height/2,t;gs.left!=(t=left+"px")&&(gs.left=t);gs.top!=(t=top+"px")&&(gs.top=t);this.X=pathlike[has](this.type)?-left:x;this.Y=pathlike[has](this.type)?-top:y;this.W=w;this.H=h;if(pathlike[has](this.type)){os.left!=(t=-left*zoom+"px")&&(os.left=t);os.top!=(t=-top*zoom+"px")&&(os.top=t);}else if(this.type=="text"){os.left!=(t=-left+"px")&&(os.left=t);os.top!=(t=-top+"px")&&(os.top=t);}else {gs.width!=(t=this.paper.width+"px")&&(gs.width=t);gs.height!=(t=this.paper.height+"px")&&(gs.height=t);os.left!=(t=x-left+"px")&&(os.left=t);os.top!=(t=y-top+"px")&&(os.top=t);os.width!=(t=w+"px")&&(os.width=t);os.height!=(t=h+"px")&&(os.height=t);}};elproto.hide=function(){!this.removed&&(this.Group.style.display="none");return this};elproto.show=function(){!this.removed&&(this.Group.style.display="block");return this};elproto.getBBox=function(){if(this.removed){return this}if(pathlike[has](this.type)){return pathDimensions(this.attrs.path)}return {x:this.X+(this.bbx||0),y:this.Y,width:this.W,height:this.H}};elproto.remove=function(){if(this.removed){return}tear(this,this.paper);this.node.parentNode.removeChild(this.node);this.Group.parentNode.removeChild(this.Group);this.shape&&this.shape.parentNode.removeChild(this.shape);for(var i in this){delete this[i];}this.removed=true;};elproto.attr=function(name,value){if(this.removed){return this}if(name==null){var res={};for(var i in this.attrs)if(this.attrs[has](i)){res[i]=this.attrs[i];}this._.rt.deg&&(res.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(res.scale=this.scale());res.gradient&&res.fill=="none"&&(res.fill=res.gradient)&&delete res.gradient;return res}if(value==null&&R.is(name,"string")){if(name=="translation"){return translate.call(this)}if(name=="rotation"){return this.rotate()}if(name=="scale"){return this.scale()}if(name==fillString&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient}return this.attrs[name]}if(this.attrs&&value==null&&R.is(name,array)){var ii1,values={};for(i=0,ii1=name[length];i<ii1;i++){values[name[i]]=this.attr(name[i]);}return values}var params;if(value!=null){params={};params[name]=value;}value==null&&R.is(name,"object")&&(params=name);if(params){for(var key in this.paper.customAttributes)if(this.paper.customAttributes[has](key)&&params[has](key)&&R.is(this.paper.customAttributes[key],"function")){var par=this.paper.customAttributes[key].apply(this,[][concat](params[key]));this.attrs[key]=params[key];for(var subkey in par)if(par[has](subkey)){params[subkey]=par[subkey];}}if(params.text&&this.type=="text"){this.node.string=params.text;}setFillAndStroke(this,params);if(params.gradient&&(({circle:1,ellipse:1})[has](this.type)||Str(params.gradient).charAt()!="r")){addGradientFill(this,params.gradient);}(!pathlike[has](this.type)||this._.rt.deg)&&this.setBox(this.attrs);}return this};elproto.toFront=function(){!this.removed&&this.Group.parentNode[appendChild](this.Group);this.paper.top!=this&&tofront(this,this.paper);return this};elproto.toBack=function(){if(this.removed){return this}if(this.Group.parentNode.firstChild!=this.Group){this.Group.parentNode.insertBefore(this.Group,this.Group.parentNode.firstChild);toback(this,this.paper);}return this};elproto.insertAfter=function(element){if(this.removed){return this}if(element.constructor==Set){element=element[element.length-1];}if(element.Group.nextSibling){element.Group.parentNode.insertBefore(this.Group,element.Group.nextSibling);}else {element.Group.parentNode[appendChild](this.Group);}insertafter(this,element,this.paper);return this};elproto.insertBefore=function(element){if(this.removed){return this}if(element.constructor==Set){element=element[0];}element.Group.parentNode.insertBefore(this.Group,element.Group);insertbefore(this,element,this.paper);return this};elproto.blur=function(size){var s=this.node.runtimeStyle,f=s.filter;f=f.replace(blurregexp,E);if(+size!==0){this.attrs.blur=size;s.filter=f+S+ms+".Blur(pixelradius="+(+size||1.5)+")";s.margin=R.format("-{0}px 0 0 -{0}px",round(+size||1.5));}else {s.filter=f;s.margin=0;delete this.attrs.blur;}};theCircle=function(vml,x,y,r){var g=createNode("group"),o=createNode("oval");o.style;g.style.cssText="position:absolute;left:0;top:0;width:"+vml.width+"px;height:"+vml.height+"px";g.coordsize=coordsize;g.coordorigin=vml.coordorigin;g[appendChild](o);var res=new Element(o,g,vml);res.type="circle";setFillAndStroke(res,{stroke:"#000",fill:"none"});res.attrs.cx=x;res.attrs.cy=y;res.attrs.r=r;res.setBox({x:x-r,y:y-r,width:r*2,height:r*2});vml.canvas[appendChild](g);return res};function rectPath(x,y,w,h,r){if(r){return R.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z",x+r,y,w-r*2,r,-r,h-r*2,r*2-w,r*2-h)}else {return R.format("M{0},{1}l{2},0,0,{3},{4},0z",x,y,w,h,-w)}}theRect=function(vml,x,y,w,h,r){var path=rectPath(x,y,w,h,r),res=vml.path(path),a=res.attrs;res.X=a.x=x;res.Y=a.y=y;res.W=a.width=w;res.H=a.height=h;a.r=r;a.path=path;res.type="rect";return res};theEllipse=function(vml,x,y,rx,ry){var g=createNode("group"),o=createNode("oval");o.style;g.style.cssText="position:absolute;left:0;top:0;width:"+vml.width+"px;height:"+vml.height+"px";g.coordsize=coordsize;g.coordorigin=vml.coordorigin;g[appendChild](o);var res=new Element(o,g,vml);res.type="ellipse";setFillAndStroke(res,{stroke:"#000"});res.attrs.cx=x;res.attrs.cy=y;res.attrs.rx=rx;res.attrs.ry=ry;res.setBox({x:x-rx,y:y-ry,width:rx*2,height:ry*2});vml.canvas[appendChild](g);return res};theImage=function(vml,src,x,y,w,h){var g=createNode("group"),o=createNode("image");g.style.cssText="position:absolute;left:0;top:0;width:"+vml.width+"px;height:"+vml.height+"px";g.coordsize=coordsize;g.coordorigin=vml.coordorigin;o.src=src;g[appendChild](o);var res=new Element(o,g,vml);res.type="image";res.attrs.src=src;res.attrs.x=x;res.attrs.y=y;res.attrs.w=w;res.attrs.h=h;res.setBox({x:x,y:y,width:w,height:h});vml.canvas[appendChild](g);return res};theText=function(vml,x,y,text){var g=createNode("group"),el=createNode("shape"),ol=el.style,path=createNode("path");path.style;var o=createNode("textpath");g.style.cssText="position:absolute;left:0;top:0;width:"+vml.width+"px;height:"+vml.height+"px";g.coordsize=coordsize;g.coordorigin=vml.coordorigin;path.v=R.format("m{0},{1}l{2},{1}",round(x*10),round(y*10),round(x*10)+1);path.textpathok=true;ol.width=vml.width;ol.height=vml.height;o.string=Str(text);o.on=true;el[appendChild](o);el[appendChild](path);g[appendChild](el);var res=new Element(o,g,vml);res.shape=el;res.textpath=path;res.type="text";res.attrs.text=text;res.attrs.x=x;res.attrs.y=y;res.attrs.w=1;res.attrs.h=1;setFillAndStroke(res,{font:availableAttrs.font,stroke:"none",fill:"#000"});res.setBox();vml.canvas[appendChild](g);return res};setSize=function(width,height){var cs=this.canvas.style;width==+width&&(width+="px");height==+height&&(height+="px");cs.width=width;cs.height=height;cs.clip="rect(0 "+width+" "+height+" 0)";return this};var createNode;doc.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!doc.namespaces.rvml&&doc.namespaces.add("rvml","urn:schemas-microsoft-com:vml");createNode=function(tagName){return doc.createElement("<rvml:"+tagName+' class="rvml">')};}catch(e){createNode=function(tagName){return doc.createElement("<"+tagName+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')};}create=function(){var con=getContainer[apply](0,arguments),container=con.container,height=con.height,width=con.width,x=con.x,y=con.y;if(!container){throw new Error("VML container not found.")}var res=new Paper,c=res.canvas=doc.createElement("div"),cs=c.style;x=x||0;y=y||0;width=width||512;height=height||342;width==+width&&(width+="px");height==+height&&(height+="px");res.width=1e3;res.height=1e3;res.coordsize=zoom*1e3+S+zoom*1e3;res.coordorigin="0 0";res.span=doc.createElement("span");res.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";c[appendChild](res.span);cs.cssText=R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",width,height);if(container==1){doc.body[appendChild](c);cs.left=x+"px";cs.top=y+"px";cs.position="absolute";}else {if(container.firstChild){container.insertBefore(c,container.firstChild);}else {container[appendChild](c);}}plugins.call(res,res,R.fn);return res};paperproto.clear=function(){this.canvas.innerHTML=E;this.span=doc.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[appendChild](this.span);this.bottom=this.top=null;};paperproto.remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var i in this){this[i]=removed(i);}return true};}var version=navigator.userAgent.match(/Version\/(.*?)\s/);if(navigator.vendor=="Apple Computer, Inc."&&(version&&version[1]<4||navigator.platform.slice(0,2)=="iP")){paperproto.safari=function(){var rect=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});win.setTimeout(function(){rect.remove();});};}else {paperproto.safari=function(){};}var preventDefault=function(){this.returnValue=false;},preventTouch=function(){return this.originalEvent.preventDefault()},stopPropagation=function(){this.cancelBubble=true;},stopTouch=function(){return this.originalEvent.stopPropagation()},addEvent=function(){if(doc.addEventListener){return function(obj,type,fn,element){var realName=supportsTouch&&touchMap[type]?touchMap[type]:type;var f=function(e){if(supportsTouch&&touchMap[has](type)){for(var i=0,ii1=e.targetTouches&&e.targetTouches.length;i<ii1;i++){if(e.targetTouches[i].target==obj){var olde=e;e=e.targetTouches[i];e.originalEvent=olde;e.preventDefault=preventTouch;e.stopPropagation=stopTouch;break}}}return fn.call(element,e)};obj.addEventListener(realName,f,false);return function(){obj.removeEventListener(realName,f,false);return true}}}else if(doc.attachEvent){return function(obj,type,fn,element){var f=function(e){e=e||win.event;e.preventDefault=e.preventDefault||preventDefault;e.stopPropagation=e.stopPropagation||stopPropagation;return fn.call(element,e)};obj.attachEvent("on"+type,f);var detacher=function(){obj.detachEvent("on"+type,f);return true};return detacher}}}(),drag=[],dragMove=function(e){var x=e.clientX,y=e.clientY,scrollY=doc.documentElement.scrollTop||doc.body.scrollTop,scrollX=doc.documentElement.scrollLeft||doc.body.scrollLeft,dragi,j=drag.length;while(j--){dragi=drag[j];if(supportsTouch){var i=e.touches.length,touch;while(i--){touch=e.touches[i];if(touch.identifier==dragi.el._drag.id){x=touch.clientX;y=touch.clientY;(e.originalEvent?e.originalEvent:e).preventDefault();break}}}else {e.preventDefault();}x+=scrollX;y+=scrollY;dragi.move&&dragi.move.call(dragi.move_scope||dragi.el,x-dragi.el._drag.x,y-dragi.el._drag.y,x,y,e);}},dragUp=function(e){R.unmousemove(dragMove).unmouseup(dragUp);var i=drag.length,dragi;while(i--){dragi=drag[i];dragi.el._drag={};dragi.end&&dragi.end.call(dragi.end_scope||dragi.start_scope||dragi.move_scope||dragi.el,e);}drag=[];};for(var i=events[length];i--;){(function(eventName){R[eventName]=Element[proto][eventName]=function(fn,scope){if(R.is(fn,"function")){this.events=this.events||[];this.events.push({name:eventName,f:fn,unbind:addEvent(this.shape||this.node||doc,eventName,fn,scope||this)});}return this};R["un"+eventName]=Element[proto]["un"+eventName]=function(fn){var events=this.events,l=events[length];while(l--)if(events[l].name==eventName&&events[l].f==fn){events[l].unbind();events.splice(l,1);!events.length&&delete this.events;return this}return this};})(events[i]);}elproto.hover=function(f_in,f_out,scope_in,scope_out){return this.mouseover(f_in,scope_in).mouseout(f_out,scope_out||scope_in)};elproto.unhover=function(f_in,f_out){return this.unmouseover(f_in).unmouseout(f_out)};elproto.drag=function(onmove,onstart,onend,move_scope,start_scope,end_scope){this._drag={};this.mousedown(function(e){(e.originalEvent||e).preventDefault();var scrollY=doc.documentElement.scrollTop||doc.body.scrollTop,scrollX=doc.documentElement.scrollLeft||doc.body.scrollLeft;this._drag.x=e.clientX+scrollX;this._drag.y=e.clientY+scrollY;this._drag.id=e.identifier;onstart&&onstart.call(start_scope||move_scope||this,e.clientX+scrollX,e.clientY+scrollY,e);!drag.length&&R.mousemove(dragMove).mouseup(dragUp);drag.push({el:this,move:onmove,end:onend,move_scope:move_scope,start_scope:start_scope,end_scope:end_scope});});return this};elproto.undrag=function(onmove,onstart,onend){var i=drag.length;while(i--){drag[i].el==this&&drag[i].move==onmove&&drag[i].end==onend&&drag.splice(i++,1);}!drag.length&&R.unmousemove(dragMove).unmouseup(dragUp);};paperproto.circle=function(x,y,r){return theCircle(this,x||0,y||0,r||0)};paperproto.rect=function(x,y,w,h,r){return theRect(this,x||0,y||0,w||0,h||0,r||0)};paperproto.ellipse=function(x,y,rx,ry){return theEllipse(this,x||0,y||0,rx||0,ry||0)};paperproto.path=function(pathString){pathString&&!R.is(pathString,string)&&!R.is(pathString[0],array)&&(pathString+=E);return thePath(R.format[apply](R,arguments),this)};paperproto.image=function(src,x,y,w,h){return theImage(this,src||"about:blank",x||0,y||0,w||0,h||0)};paperproto.text=function(x,y,text){return theText(this,x||0,y||0,Str(text))};paperproto.set=function(itemsArray){arguments[length]>1&&(itemsArray=Array[proto].splice.call(arguments,0,arguments[length]));return new Set(itemsArray)};paperproto.setSize=setSize;paperproto.top=paperproto.bottom=null;paperproto.raphael=R;function x_y(){return this.x+S+this.y}elproto.resetScale=function(){if(this.removed){return this}this._.sx=1;this._.sy=1;this.attrs.scale="1 1";};elproto.scale=function(x,y,cx,cy){if(this.removed){return this}if(x==null&&y==null){return {x:this._.sx,y:this._.sy,toString:x_y}}y=y||x;!+y&&(y=x);var dx,dy,a=this.attrs;if(x!=0){var bb=this.getBBox(),rcx=bb.x+bb.width/2,rcy=bb.y+bb.height/2,kx=abs(x/this._.sx),ky=abs(y/this._.sy);cx=+cx||cx==0?cx:rcx;cy=+cy||cy==0?cy:rcy;var posx=this._.sx>0,posy=this._.sy>0,dirx=~~(x/abs(x)),diry=~~(y/abs(y)),dkx=kx*dirx,dky=ky*diry,s=this.node.style,ncx=cx+abs(rcx-cx)*dkx*(rcx>cx==posx?1:-1),ncy=cy+abs(rcy-cy)*dky*(rcy>cy==posy?1:-1),fr=x*dirx>y*diry?ky:kx;switch(this.type){case "rect":case "image":var neww=a.width*kx,newh=a.height*ky;this.attr({height:newh,r:a.r*fr,width:neww,x:ncx-neww/2,y:ncy-newh/2});break;case "circle":case "ellipse":this.attr({rx:a.rx*kx,ry:a.ry*ky,r:a.r*fr,cx:ncx,cy:ncy});break;case "text":this.attr({x:ncx,y:ncy});break;case "path":var path=pathToRelative(a.path),skip=true,fx=posx?dkx:kx,fy=posy?dky:ky;for(var i=0,ii1=path[length];i<ii1;i++){var p=path[i],P0=upperCase.call(p[0]);if(P0=="M"&&skip){continue}else {skip=false;}if(P0=="A"){p[path[i][length]-2]*=fx;p[path[i][length]-1]*=fy;p[1]*=kx;p[2]*=ky;p[5]=+(dirx+diry?!!+p[5]:!+p[5]);}else if(P0=="H"){for(var j=1,jj=p[length];j<jj;j++){p[j]*=fx;}}else if(P0=="V"){for(j=1,jj=p[length];j<jj;j++){p[j]*=fy;}}else {for(j=1,jj=p[length];j<jj;j++){p[j]*=j%2?fx:fy;}}}var dim2=pathDimensions(path);dx=ncx-dim2.x-dim2.width/2;dy=ncy-dim2.y-dim2.height/2;path[0][1]+=dx;path[0][2]+=dy;this.attr({path:path});break}if(this.type in{text:1,image:1}&&(dirx!=1||diry!=1)){if(this.transformations){this.transformations[2]="scale("[concat](dirx,",",diry,")");setAttr(this.node,"transform",this.transformations[join](S));dx=dirx==-1?-a.x-(neww||0):a.x;dy=diry==-1?-a.y-(newh||0):a.y;this.attr({x:dx,y:dy});a.fx=dirx-1;a.fy=diry-1;}else {this.node.filterMatrix=ms+".Matrix(M11="[concat](dirx,", M12=0, M21=0, M22=",diry,", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')");s.filter=(this.node.filterMatrix||E)+(this.node.filterOpacity||E);}}else {if(this.transformations){this.transformations[2]=E;setAttr(this.node,"transform",this.transformations[join](S));a.fx=0;a.fy=0;}else {this.node.filterMatrix=E;s.filter=(this.node.filterMatrix||E)+(this.node.filterOpacity||E);}}a.scale=[x,y,cx,cy][join](S);this._.sx=x;this._.sy=y;}return this};elproto.clone=function(){if(this.removed){return null}var attr=this.attr();delete attr.scale;delete attr.translation;return this.paper[this.type]().attr(attr)};var curveslengths={},getPointAtSegmentLength=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,length){if(p1x===c1x&&p1y===c1y&&c2x===p2x&&c2y==p2y){var dx=p2x-p1x,dy=p2y-p1y;var totalLength=Math.sqrt(dx*dx+dy*dy);if(length==null){return totalLength}else {var fract=length/totalLength;return {start:{x:p1x,y:p1y},m:{x:p1x,y:p1y},n:{x:p2x,y:p2y},end:{x:p2x,y:p2y},x:p1x+fract*dx,y:p1y+fract*dy,alpha:90-math.atan(dx/dy)*180/PI}}}var len=0,precision=100,name=[p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y].join(),cache=curveslengths[name],old,dot;!cache&&(curveslengths[name]=cache={data:[]});cache.timer&&clearTimeout(cache.timer);cache.timer=setTimeout(function(){delete curveslengths[name];},2e3);if(length!=null){var total=getPointAtSegmentLength(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y);precision=~~total*10;}for(var i=0;i<precision+1;i++){if(cache.data[length]>i){dot=cache.data[i*precision];}else {dot=R.findDotsAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,i/precision);cache.data[i]=dot;}i&&(len+=pow(pow(old.x-dot.x,2)+pow(old.y-dot.y,2),.5));if(length!=null&&len>=length){return dot}old=dot;}if(length==null){return len}},getLengthFactory=function(istotal,subpath){return function(path,length,onlystart){path=path2curve(path);var x,y,p,l,sp="",subpaths={},point,len=0;for(var i=0,ii1=path.length;i<ii1;i++){p=path[i];if(p[0]=="M"){x=+p[1];y=+p[2];}else {l=getPointAtSegmentLength(x,y,p[1],p[2],p[3],p[4],p[5],p[6]);if(len+l>length){if(subpath&&!subpaths.start){point=getPointAtSegmentLength(x,y,p[1],p[2],p[3],p[4],p[5],p[6],length-len);sp+=["C",point.start.x,point.start.y,point.m.x,point.m.y,point.x,point.y];if(onlystart){return sp}subpaths.start=sp;sp=["M",point.x,point.y+"C",point.n.x,point.n.y,point.end.x,point.end.y,p[5],p[6]][join]();len+=l;x=+p[5];y=+p[6];continue}if(!istotal&&!subpath){point=getPointAtSegmentLength(x,y,p[1],p[2],p[3],p[4],p[5],p[6],length-len);return {x:point.x,y:point.y,alpha:point.alpha}}}len+=l;x=+p[5];y=+p[6];}sp+=p;}subpaths.end=sp;point=istotal?len:subpath?subpaths:R.findDotsAtSegment(x,y,p[1],p[2],p[3],p[4],p[5],p[6],1);point.alpha&&(point={x:point.x,y:point.y,alpha:point.alpha});return point}};var getTotalLength=getLengthFactory(1),getPointAtLength=getLengthFactory(),getSubpathsAtLength=getLengthFactory(0,1);elproto.getTotalLength=function(){if(this.type!="path"){return}if(this.node.getTotalLength){return this.node.getTotalLength()}return getTotalLength(this.attrs.path)};elproto.getPointAtLength=function(length){if(this.type!="path"){return}return getPointAtLength(this.attrs.path,length)};elproto.getSubpath=function(from,to){if(this.type!="path"){return}if(abs(this.getTotalLength()-to)<"1e-6"){return getSubpathsAtLength(this.attrs.path,from).end}var a=getSubpathsAtLength(this.attrs.path,to,1);return from?getSubpathsAtLength(a,from).end:a};R.easing_formulas={linear:function(n){return n},"<":function(n){return pow(n,3)},">":function(n){return pow(n-1,3)+1},"<>":function(n){n=n*2;if(n<1){return pow(n,3)/2}n-=2;return (pow(n,3)+2)/2},backIn:function(n){var s=1.70158;return n*n*((s+1)*n-s)},backOut:function(n){n=n-1;var s=1.70158;return n*n*((s+1)*n+s)+1},elastic:function(n){if(n==0||n==1){return n}var p=.3,s=p/4;return pow(2,-10*n)*math.sin((n-s)*(2*PI)/p)+1},bounce:function(n){var s=7.5625,p=2.75,l;if(n<1/p){l=s*n*n;}else {if(n<2/p){n-=1.5/p;l=s*n*n+.75;}else {if(n<2.5/p){n-=2.25/p;l=s*n*n+.9375;}else {n-=2.625/p;l=s*n*n+.984375;}}}return l}};var animationElements=[],animation=function(){var Now=+new Date;for(var l=0;l<animationElements[length];l++){var e=animationElements[l];if(e.stop||e.el.removed){continue}var time=Now-e.start,ms=e.ms,easing=e.easing,from=e.from,diff=e.diff,to=e.to,t=e.t,that=e.el,set={},now;if(time<ms){var pos=easing(time/ms);for(var attr in from)if(from[has](attr)){switch(availableAnimAttrs[attr]){case "along":now=pos*ms*diff[attr];to.back&&(now=to.len-now);var point=getPointAtLength(to[attr],now);that.translate(diff.sx-diff.x||0,diff.sy-diff.y||0);diff.x=point.x;diff.y=point.y;that.translate(point.x-diff.sx,point.y-diff.sy);to.rot&&that.rotate(diff.r+point.alpha,point.x,point.y);break;case nu:now=+from[attr]+pos*ms*diff[attr];break;case "colour":now="rgb("+[upto255(round(from[attr].r+pos*ms*diff[attr].r)),upto255(round(from[attr].g+pos*ms*diff[attr].g)),upto255(round(from[attr].b+pos*ms*diff[attr].b))][join](",")+")";break;case "path":now=[];for(var i=0,ii1=from[attr][length];i<ii1;i++){now[i]=[from[attr][i][0]];for(var j=1,jj=from[attr][i][length];j<jj;j++){now[i][j]=+from[attr][i][j]+pos*ms*diff[attr][i][j];}now[i]=now[i][join](S);}now=now[join](S);break;case "csv":switch(attr){case "translation":var x=pos*ms*diff[attr][0]-t.x,y=pos*ms*diff[attr][1]-t.y;t.x+=x;t.y+=y;now=x+S+y;break;case "rotation":now=+from[attr][0]+pos*ms*diff[attr][0];from[attr][1]&&(now+=","+from[attr][1]+","+from[attr][2]);break;case "scale":now=[+from[attr][0]+pos*ms*diff[attr][0],+from[attr][1]+pos*ms*diff[attr][1],2 in to[attr]?to[attr][2]:E,3 in to[attr]?to[attr][3]:E][join](S);break;case "clip-rect":now=[];i=4;while(i--){now[i]=+from[attr][i]+pos*ms*diff[attr][i];}break}break;default:var from2=[].concat(from[attr]);now=[];i=that.paper.customAttributes[attr].length;while(i--){now[i]=+from2[i]+pos*ms*diff[attr][i];}break}set[attr]=now;}that.attr(set);that._run&&that._run.call(that);}else {if(to.along){point=getPointAtLength(to.along,to.len*!to.back);that.translate(diff.sx-(diff.x||0)+point.x-diff.sx,diff.sy-(diff.y||0)+point.y-diff.sy);to.rot&&that.rotate(diff.r+point.alpha,point.x,point.y);}(t.x||t.y)&&that.translate(-t.x,-t.y);to.scale&&(to.scale+=E);that.attr(to);animationElements.splice(l--,1);}}R.svg&&that&&that.paper&&that.paper.safari();animationElements[length]&&setTimeout(animation);},keyframesRun=function(attr,element,time,prev,prevcallback){var dif=time-prev;element.timeouts.push(setTimeout(function(){R.is(prevcallback,"function")&&prevcallback.call(element);element.animate(attr,dif,attr.easing);},prev));},upto255=function(color){return mmax(mmin(color,255),0)},translate=function(x,y){if(x==null){return {x:this._.tx,y:this._.ty,toString:x_y}}this._.tx+=+x;this._.ty+=+y;switch(this.type){case "circle":case "ellipse":this.attr({cx:+x+this.attrs.cx,cy:+y+this.attrs.cy});break;case "rect":case "image":case "text":this.attr({x:+x+this.attrs.x,y:+y+this.attrs.y});break;case "path":var path=pathToRelative(this.attrs.path);path[0][1]+=+x;path[0][2]+=+y;this.attr({path:path});break}return this};elproto.animateWith=function(element,params,ms,easing,callback){for(var i=0,ii1=animationElements.length;i<ii1;i++){if(animationElements[i].el.id==element.id){params.start=animationElements[i].start;}}return this.animate(params,ms,easing,callback)};elproto.animateAlong=along();elproto.animateAlongBack=along(1);function along(isBack){return function(path,ms,rotate,callback){var params={back:isBack};R.is(rotate,"function")?callback=rotate:params.rot=rotate;path&&path.constructor==Element&&(path=path.attrs.path);path&&(params.along=path);return this.animate(params,ms,callback)}}function CubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration){var cx=3*p1x,bx=3*(p2x-p1x)-cx,ax=1-cx-bx,cy=3*p1y,by=3*(p2y-p1y)-cy,ay=1-cy-by;function sampleCurveX(t){return ((ax*t+bx)*t+cx)*t}function solve(x,epsilon){var t=solveCurveX(x,epsilon);return ((ay*t+by)*t+cy)*t}function solveCurveX(x,epsilon){var t0,t1,t2,x2,d2,i;for(t2=x,i=0;i<8;i++){x2=sampleCurveX(t2)-x;if(abs(x2)<epsilon){return t2}d2=(3*ax*t2+2*bx)*t2+cx;if(abs(d2)<1e-6){break}t2=t2-x2/d2;}t0=0;t1=1;t2=x;if(t2<t0){return t0}if(t2>t1){return t1}while(t0<t1){x2=sampleCurveX(t2);if(abs(x2-x)<epsilon){return t2}if(x>x2){t0=t2;}else {t1=t2;}t2=(t1-t0)/2+t0;}return t2}return solve(t,1/(200*duration))}elproto.onAnimation=function(f){this._run=f||0;return this};elproto.animate=function(params,ms,easing,callback){var element=this;element.timeouts=element.timeouts||[];if(R.is(easing,"function")||!easing){callback=easing||null;}if(element.removed){callback&&callback.call(element);return element}var from={},to={},animateable=false,diff={};for(var attr in params)if(params[has](attr)){if(availableAnimAttrs[has](attr)||element.paper.customAttributes[has](attr)){animateable=true;from[attr]=element.attr(attr);from[attr]==null&&(from[attr]=availableAttrs[attr]);to[attr]=params[attr];switch(availableAnimAttrs[attr]){case "along":var len=getTotalLength(params[attr]);var point=getPointAtLength(params[attr],len*!!params.back);var bb=element.getBBox();diff[attr]=len/ms;diff.tx=bb.x;diff.ty=bb.y;diff.sx=point.x;diff.sy=point.y;to.rot=params.rot;to.back=params.back;to.len=len;params.rot&&(diff.r=toFloat(element.rotate())||0);break;case nu:diff[attr]=(to[attr]-from[attr])/ms;break;case "colour":from[attr]=R.getRGB(from[attr]);var toColour=R.getRGB(to[attr]);diff[attr]={r:(toColour.r-from[attr].r)/ms,g:(toColour.g-from[attr].g)/ms,b:(toColour.b-from[attr].b)/ms};break;case "path":var pathes=path2curve(from[attr],to[attr]);from[attr]=pathes[0];var toPath=pathes[1];diff[attr]=[];for(var i=0,ii1=from[attr][length];i<ii1;i++){diff[attr][i]=[0];for(var j=1,jj=from[attr][i][length];j<jj;j++){diff[attr][i][j]=(toPath[i][j]-from[attr][i][j])/ms;}}break;case "csv":var values=Str(params[attr])[split](separator),from2=Str(from[attr])[split](separator);switch(attr){case "translation":from[attr]=[0,0];diff[attr]=[values[0]/ms,values[1]/ms];break;case "rotation":from[attr]=from2[1]==values[1]&&from2[2]==values[2]?from2:[0,values[1],values[2]];diff[attr]=[(values[0]-from[attr][0])/ms,0,0];break;case "scale":params[attr]=values;from[attr]=Str(from[attr])[split](separator);diff[attr]=[(values[0]-from[attr][0])/ms,(values[1]-from[attr][1])/ms,0,0];break;case "clip-rect":from[attr]=Str(from[attr])[split](separator);diff[attr]=[];i=4;while(i--){diff[attr][i]=(values[i]-from[attr][i])/ms;}break}to[attr]=values;break;default:values=[].concat(params[attr]);from2=[].concat(from[attr]);diff[attr]=[];i=element.paper.customAttributes[attr][length];while(i--){diff[attr][i]=((values[i]||0)-(from2[i]||0))/ms;}break}}}if(!animateable){var attrs=[],lastcall;for(var key in params)if(params[has](key)&&animKeyFrames.test(key)){attr={value:params[key]};key=="from"&&(key=0);key=="to"&&(key=100);attr.key=toInt(key,10);attrs.push(attr);}attrs.sort(sortByKey);if(attrs[0].key){attrs.unshift({key:0,value:element.attrs});}for(i=0,ii1=attrs[length];i<ii1;i++){keyframesRun(attrs[i].value,element,ms/100*attrs[i].key,ms/100*(attrs[i-1]&&attrs[i-1].key||0),attrs[i-1]&&attrs[i-1].value.callback);}lastcall=attrs[attrs[length]-1].value.callback;if(lastcall){element.timeouts.push(setTimeout(function(){lastcall.call(element);},ms));}}else {var easyeasy=R.easing_formulas[easing];if(!easyeasy){easyeasy=Str(easing).match(bezierrg);if(easyeasy&&easyeasy[length]==5){var curve=easyeasy;easyeasy=function(t){return CubicBezierAtTime(t,+curve[1],+curve[2],+curve[3],+curve[4],ms)};}else {easyeasy=function(t){return t};}}animationElements.push({start:params.start||+new Date,ms:ms,easing:easyeasy,from:from,diff:diff,to:to,el:element,t:{x:0,y:0}});R.is(callback,"function")&&(element._ac=setTimeout(function(){callback.call(element);},ms));animationElements[length]==1&&setTimeout(animation);}return this};elproto.stop=function(){for(var i=0;i<animationElements.length;i++){animationElements[i].el.id==this.id&&animationElements.splice(i--,1);}for(i=0,ii=this.timeouts&&this.timeouts.length;i<ii;i++){clearTimeout(this.timeouts[i]);}this.timeouts=[];clearTimeout(this._ac);delete this._ac;return this};elproto.translate=function(x,y){return this.attr({translation:x+" "+y})};elproto[toString]=function(){return "Raphaël’s object"};R.ae=animationElements;var Set=function(items){this.items=[];this[length]=0;this.type="set";if(items){for(var i=0,ii1=items[length];i<ii1;i++){if(items[i]&&(items[i].constructor==Element||items[i].constructor==Set)){this[this.items[length]]=this.items[this.items[length]]=items[i];this[length]++;}}}};Set[proto][push]=function(){var item,len;for(var i=0,ii1=arguments[length];i<ii1;i++){item=arguments[i];if(item&&(item.constructor==Element||item.constructor==Set)){len=this.items[length];this[len]=this.items[len]=item;this[length]++;}}return this};Set[proto].pop=function(){delete this[this[length]--];return this.items.pop()};for(var method in elproto)if(elproto[has](method)){Set[proto][method]=function(methodname){return function(){for(var i=0,ii1=this.items[length];i<ii1;i++){this.items[i][methodname][apply](this.items[i],arguments);}return this}}(method);}Set[proto].attr=function(name,value){if(name&&R.is(name,array)&&R.is(name[0],"object")){for(var j=0,jj=name[length];j<jj;j++){this.items[j].attr(name[j]);}}else {for(var i=0,ii1=this.items[length];i<ii1;i++){this.items[i].attr(name,value);}}return this};Set[proto].animate=function(params,ms,easing,callback){(R.is(easing,"function")||!easing)&&(callback=easing||null);var len=this.items[length],i=len,item,set=this,collector;callback&&(collector=function(){!--len&&callback.call(set);});easing=R.is(easing,string)?easing:collector;item=this.items[--i].animate(params,ms,easing,collector);while(i--){this.items[i]&&!this.items[i].removed&&this.items[i].animateWith(item,params,ms,easing,collector);}return this};Set[proto].insertAfter=function(el){var i=this.items[length];while(i--){this.items[i].insertAfter(el);}return this};Set[proto].getBBox=function(){var x=[],y=[],w=[],h=[];for(var i=this.items[length];i--;){var box=this.items[i].getBBox();x[push](box.x);y[push](box.y);w[push](box.x+box.width);h[push](box.y+box.height);}x=mmin[apply](0,x);y=mmin[apply](0,y);return {x:x,y:y,width:mmax[apply](0,w)-x,height:mmax[apply](0,h)-y}};Set[proto].clone=function(s){s=new Set;for(var i=0,ii1=this.items[length];i<ii1;i++){s[push](this.items[i].clone());}return s};R.registerFont=function(font){if(!font.face){return font}this.fonts=this.fonts||{};var fontcopy={w:font.w,face:{},glyphs:{}},family=font.face["font-family"];for(var prop in font.face)if(font.face[has](prop)){fontcopy.face[prop]=font.face[prop];}if(this.fonts[family]){this.fonts[family][push](fontcopy);}else {this.fonts[family]=[fontcopy];}if(!font.svg){fontcopy.face["units-per-em"]=toInt(font.face["units-per-em"],10);for(var glyph in font.glyphs)if(font.glyphs[has](glyph)){var path=font.glyphs[glyph];fontcopy.glyphs[glyph]={w:path.w,k:{},d:path.d&&"M"+path.d[rp](/[mlcxtrv]/g,function(command){return ({l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"})[command]||"M"})+"z"};if(path.k){for(var k in path.k)if(path[has](k)){fontcopy.glyphs[glyph].k[k]=path.k[k];}}}}return font};paperproto.getFont=function(family,weight,style,stretch){stretch=stretch||"normal";style=style||"normal";weight=+weight||({normal:400,bold:700,lighter:300,bolder:800})[weight]||400;if(!R.fonts){return}var font=R.fonts[family];if(!font){var name=new RegExp("(^|\\s)"+family[rp](/[^\w\d\s+!~.:_-]/g,E)+"(\\s|$)","i");for(var fontName in R.fonts)if(R.fonts[has](fontName)){if(name.test(fontName)){font=R.fonts[fontName];break}}}var thefont;if(font){for(var i=0,ii1=font[length];i<ii1;i++){thefont=font[i];if(thefont.face["font-weight"]==weight&&(thefont.face["font-style"]==style||!thefont.face["font-style"])&&thefont.face["font-stretch"]==stretch){break}}}return thefont};paperproto.print=function(x,y,string,font,size,origin,letter_spacing){origin=origin||"middle";letter_spacing=mmax(mmin(letter_spacing||0,1),-1);var out=this.set(),letters=Str(string)[split](E),shift=0,scale;R.is(font,string)&&(font=this.getFont(font));if(font){scale=(size||16)/font.face["units-per-em"];var bb=font.face.bbox.split(separator),top=+bb[0],height=+bb[1]+(origin=="baseline"?bb[3]-bb[1]+ +font.face.descent:(bb[3]-bb[1])/2);for(var i=0,ii1=letters[length];i<ii1;i++){var prev=i&&font.glyphs[letters[i-1]]||{},curr=font.glyphs[letters[i]];shift+=i?(prev.w||font.w)+(prev.k&&prev.k[letters[i]]||0)+font.w*letter_spacing:0;curr&&curr.d&&out[push](this.path(curr.d).attr({fill:"#000",stroke:"none",translation:[shift,0]}));}out.scale(scale,scale,top,height).translate(x-top,y-height);}return out};R.format=function(token,params){var args=R.is(params,array)?[0][concat](params):arguments;token&&R.is(token,string)&&args[length]-1&&(token=token[rp](formatrg,function(str,i){return args[++i]==null?E:args[i]}));return token||E};R.ninja=function(){oldRaphael.was?win.Raphael=oldRaphael.is:Raphael=undefined;return R};R.el=elproto;R.st=Set[proto];return R})();
1519
1520
 
1520
- const KhanColors={BLUE:color.blue,ORANGE:"#FFA500",PINK:"#FF00AF",GREEN:color.green,PURPLE:"#9D38BD",RED:"#DF0030",GRAY:"gray",BLACK:"black",LIGHT_BLUE:"#9AB8ED",LIGHT_ORANGE:"#EDD19B",LIGHT_PINK:"#ED9BD3",LIGHT_GREEN:"#9BEDCE",LIGHT_PURPLE:"#DA9BED",LIGHT_RED:"#ED9AAC",LIGHT_GRAY:"#ED9B9B",LIGHT_BLACK:"#ED9B9B",GRAY10:"#D6D6D6",GRAY20:"#CDCDCD",GRAY30:"#B3B3B3",GRAY40:"#9A9A9A",GRAY50:"#808080",GRAY60:"#666666",GRAY70:"#4D4D4D",GRAY80:"#333333",GRAY90:"#1A1A1A",BLUE_A:"#CCFAFF",BLUE_B:"#80F6FF",BLUE_C:"#63D9EA",BLUE_D:"#11ACCD",BLUE_E:"#0C7F99",TEAL_A:"#94FFF5",TEAL_B:"#26EDD5",TEAL_C:"#01D1C1",TEAL_D:"#01A995",TEAL_E:"#208170",GREEN_A:"#B6FFB0",GREEN_B:"#8AF281",GREEN_C:"#74CF70",GREEN_D:"#1FAB54",GREEN_E:"#0D923F",GOLD_A:"#FFD0A9",GOLD_B:"#FFBB71",GOLD_C:"#FF9C39",GOLD_D:"#E07D10",GOLD_E:"#A75A05",RED_A:"#FCA9A9",RED_B:"#FF8482",RED_C:"#F9685D",RED_D:"#E84D39",RED_E:"#BC2612",MAROON_A:"#FFBDE0",MAROON_B:"#FF92C6",MAROON_C:"#ED5FA6",MAROON_D:"#CA337C",MAROON_E:"#9E034E",PURPLE_A:"#DDD7FF",PURPLE_B:"#C6B9FC",PURPLE_C:"#AA87FF",PURPLE_D:"#7854AB",PURPLE_E:"#543B78",MINT_A:"#F5F9E8",MINT_B:"#EDF2DF",MINT_C:"#E0E5CC",GRAY_A:"#F6F7F7",GRAY_B:"#F0F1F2",GRAY_C:"#E3E5E6",GRAY_D:"#D6D8DA",GRAY_E:"#BABEC2",GRAY_F:"#888D93",GRAY_G:"#626569",GRAY_H:"#3B3E40",GRAY_I:"#21242C",KA_BLUE:"#314453",KA_GREEN:"#71B307",_BACKGROUND:"#FDFDFD",INTERACTING:color.green,INTERACTIVE:color.green,DYNAMIC:color.blue};
1521
+ const KhanColors={BLUE:color.blue,ORANGE:"#FFA500",PINK:"#FF00AF",GREEN:color.green,PURPLE:"#9D38BD",RED:"#DF0030",GRAY:"gray",BLACK:"black",LIGHT_BLUE:"#9AB8ED",LIGHT_ORANGE:"#EDD19B",LIGHT_PINK:"#ED9BD3",LIGHT_GREEN:"#9BEDCE",LIGHT_PURPLE:"#DA9BED",LIGHT_RED:"#ED9AAC",LIGHT_GRAY:"#ED9B9B",LIGHT_BLACK:"#ED9B9B",GRAY10:"#D6D6D6",GRAY20:"#CDCDCD",GRAY30:"#B3B3B3",GRAY40:"#9A9A9A",GRAY50:"#808080",GRAY60:"#666666",GRAY70:"#4D4D4D",GRAY80:"#333333",GRAY90:"#1A1A1A",BLUE_A:"#CCFAFF",BLUE_B:"#80F6FF",BLUE_C:"#63D9EA",BLUE_D:"#11ACCD",BLUE_E:"#0C7F99",TEAL_A:"#94FFF5",TEAL_B:"#26EDD5",TEAL_C:"#01D1C1",TEAL_D:"#01A995",TEAL_E:"#208170",GREEN_A:"#B6FFB0",GREEN_B:"#8AF281",GREEN_C:"#74CF70",GREEN_D:"#1FAB54",GREEN_E:"#0D923F",GOLD_A:"#FFD0A9",GOLD_B:"#FFBB71",GOLD_C:"#FF9C39",GOLD_D:"#E07D10",GOLD_E:"#A75A05",RED_A:"#FCA9A9",RED_B:"#FF8482",RED_C:"#F9685D",RED_D:"#E84D39",RED_E:"#BC2612",MAROON_A:"#FFBDE0",MAROON_B:"#FF92C6",MAROON_C:"#ED5FA6",MAROON_D:"#CA337C",MAROON_E:"#9E034E",PURPLE_A:"#DDD7FF",PURPLE_B:"#C6B9FC",PURPLE_C:"#AA87FF",PURPLE_D:"#7854AB",PURPLE_E:"#543B78",MINT_A:"#F5F9E8",MINT_B:"#EDF2DF",MINT_C:"#E0E5CC",GRAY_A:"#F6F7F7",GRAY_B:"#F0F1F2",GRAY_C:"#E3E5E6",GRAY_D:"#D6D8DA",GRAY_E:"#BABEC2",GRAY_F:"#888D93",GRAY_G:"#626569",GRAY_H:"#3B3E40",GRAY_I:"#21242C",KA_BLUE:"#314453",KA_GREEN:"#71B307",_BACKGROUND:"#FDFDFD",INTERACTING:color.green,INTERACTIVE:color.green,DYNAMIC:color.blue};const getBackgroundColor=elementToInspect=>{const backgroundColor=window.getComputedStyle(elementToInspect).backgroundColor;if(backgroundColor!=="rgba(0, 0, 0, 0)"&&backgroundColor!=="transparent"){return backgroundColor}const parentElement=elementToInspect.parentElement;if(parentElement?.tagName.toLowerCase()==="html"||!parentElement){return "var(--wb-semanticColor-core-background-base-default)"}return getBackgroundColor(parentElement)};
1521
1522
 
1522
1523
  class DrawingTransform{constructor(raphael,initialScale,bounds){this.scaleVector=point=>{if(typeof point==="number"){return this.scaleVector([point,point])}const x=point[0];const y=point[1];return [x*this.xScale,y*this.yScale]};this.scalePoint=point=>{if(typeof point==="number"){return this.scalePoint([point,point])}const x=point[0];const y=point[1];return [(x-this.bounds.xMin)*this.xScale,(this.bounds.yMax-y)*this.yScale]};this.unscalePoint=point=>{if(typeof point==="number"){return this.unscalePoint([point,point])}const x=point[0];const y=point[1];return [x/this.xScale+this.bounds.xMin,this.bounds.yMax-y/this.yScale]};this.unscaleVector=point=>{if(typeof point==="number"){return this.unscaleVector([point,point])}return [point[0]/this.xScale,point[1]/this.yScale]};this.setScale=scale=>{if(typeof scale==="number"){scale=[scale,scale];}this.xScale=scale[0];this.yScale=scale[1];this.raphael.setSize(...this.canvasDimensions());};this.canvasDimensions=()=>{return [this.bounds.width()*this.xScale,this.bounds.height()*this.yScale]};this.pixelsPerUnitX=()=>{return this.xScale};this.pixelsPerUnitY=()=>{return this.yScale};this.raphael=raphael;this.bounds=bounds;this.xScale=initialScale[0];this.yScale=initialScale[1];this.setScale(initialScale);}}
1523
1524
 
@@ -1627,7 +1628,7 @@ function _noop(){}class InteractionTracker{constructor(trackApi,widgetType,widge
1627
1628
 
1628
1629
  const arrayRules={fence:{match:SimpleMarkdown.defaultRules.fence.match,order:1,parse:(capture,state,parse)=>({type:"codeBlock",lang:capture[2]||undefined,content:capture[3]})},paragraph:{match:SimpleMarkdown.defaultRules.paragraph.match,order:2,parse:(capture,state,parse)=>({content:capture[1]})}};const builtArrayParser=SimpleMarkdown.parserFor(arrayRules);const parseToArray=source=>{const paragraphedSource=source.replace(/^\n\s*\n/,"")+"\n\n";return builtArrayParser(paragraphedSource,{inline:false}).map(c=>{return c["content"]})};const joinFromArray=paragraphs=>paragraphs.join("\n\n");var JiptParagraphs = {parseToArray:parseToArray,joinFromArray:joinFromArray};
1629
1630
 
1630
- const denylist=["key","ref","containerSizeClass","widgetId","onChange","problemNum","apiOptions","widgetIsOpen","questionCompleted","findWidgets","onRemove","id","onBlur","onFocus","trackInteraction","keypadElement","linterContext","isLastUsedWidget","handleUserInput","analytics","showSolutions","reviewMode","widgetIndex"];function excludeDenylistKeys(obj){if(obj==null){return obj}const rv={};for(const k of Object.keys(obj)){if(!denylist.includes(k)){rv[k]=obj[k];}}return rv}
1631
+ const denylist=["key","ref","containerSizeClass","widgetId","onChange","problemNum","apiOptions","widgetIsOpen","questionCompleted","findWidgets","onRemove","id","onBlur","onFocus","trackInteraction","keypadElement","linterContext","handleUserInput","analytics","showSolutions","reviewMode","widgetIndex"];function excludeDenylistKeys(obj){if(obj==null){return obj}const rv={};for(const k of Object.keys(obj)){if(!denylist.includes(k)){rv[k]=obj[k];}}return rv}
1631
1632
 
1632
1633
  const exclamationIcon={path:"M6 11a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0-9a1 1 0 0 1 1 1v4a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1z",height:12,width:12};class Lint extends React.Component{componentDidMount(){this._positionTimeout=window.setTimeout(this.getPosition);}componentWillUnmount(){window.clearTimeout(this._positionTimeout);}render(){const{children,inline,blockHighlight,insideTable}=this.props;if(insideTable){if(inline){return jsxRuntimeExports.jsx("span",{"data-lint-inside-table":"true",children:children})}return jsxRuntimeExports.jsx("div",{"data-lint-inside-table":"true",children:children})}if(blockHighlight){return jsxRuntimeExports.jsxs("span",{className:css(styles$G.lintContainer,styles$G.lintContainerBlock),children:[this.renderLink(styles$G.radioWidgetHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}if(inline){return jsxRuntimeExports.jsxs("span",{className:css(styles$G.lintContainer),children:[this.renderLink(styles$G.inlineHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}return jsxRuntimeExports.jsxs("div",{className:css(styles$G.lintContainer),children:[this.renderLink(styles$G.hoverTarget),jsxRuntimeExports.jsx("div",{children:children})]})}constructor(...args){super(...args),this.state={tooltipAbove:true},this.getPosition=()=>{const rect=ReactDOM__default.findDOMNode(this).getBoundingClientRect();this.setState({tooltipAbove:rect.top>100});},this.renderLink=style=>{const tooltipAbove=this.state.tooltipAbove;let severityStyle;let warningText;let warningTextStyle;if(this.props.severity===1){severityStyle=styles$G.indicatorError;warningText="Error";warningTextStyle=styles$G.publishBlockingError;}else if(this.props.severity===2){severityStyle=styles$G.indicatorWarning;warningText="Warning";warningTextStyle=styles$G.warning;}else {severityStyle=styles$G.indicatorGuideline;warningText="Recommendation";warningTextStyle=styles$G.warning;}return jsxRuntimeExports.jsxs("a",{href:`https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,target:"lint-help-window",className:css(style),children:[jsxRuntimeExports.jsx("span",{className:css(styles$G.indicator,severityStyle),children:this.props.severity===1&&jsxRuntimeExports.jsx(InlineIcon,{...exclamationIcon})}),jsxRuntimeExports.jsxs("div",{className:css(styles$G.tooltip,tooltipAbove&&styles$G.tooltipAbove),children:[this.props.message.split("\n\n").map((m,i)=>jsxRuntimeExports.jsxs("p",{className:css(styles$G.tooltipParagraph),children:[jsxRuntimeExports.jsxs("span",{className:css(warningTextStyle),children:[warningText,":"," "]}),m]},i)),jsxRuntimeExports.jsx("div",{className:css(styles$G.tail,tooltipAbove&&styles$G.tailAbove)})]})]})};}}const styles$G=StyleSheet.create({lintContainer:{position:"relative"},lintContainerBlock:{display:"block"},hoverTarget:{position:"absolute",top:0,right:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ div":{outline:"1px solid "+warningColor},":hover ~ div div[data-lint-inside-table]":{outline:"1px solid "+warningColor},":hover ~ div span[data-lint-inside-table]":{backgroundColor:warningColor,color:white}},inlineHoverTarget:{float:"right",position:"relative",marginRight:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ span":{backgroundColor:warningColor,color:white}},radioWidgetHoverTarget:{position:"absolute",left:-40,display:"block",width:24,height:24,minWidth:264,":hover > span":{backgroundColor:warningColorHover},":hover > div":{display:"block",padding:8,width:280},":hover > div > div":{left:8},":hover ~ span":{backgroundColor:warningColor,color:white}},indicator:{alignItems:"center",borderRadius:4,color:"white",display:"flex",fontSize:12,height:8,justifyContent:"center",margin:8,width:8},indicatorError:{backgroundColor:"#be2612",borderRadius:8,height:16,width:16},indicatorWarning:{backgroundColor:"#f86700"},indicatorGuideline:{backgroundColor:"#ffbe26"},tooltip:{position:"absolute",right:-12,display:"none",zIndex:1e3,color:white,backgroundColor:gray17,opacity:.9,fontFamily:baseFontFamily,fontSize:"12px",lineHeight:"15px",width:"320px",borderRadius:"4px"},tooltipAbove:{bottom:32},tail:{position:"absolute",top:-12,right:16,width:0,height:0,borderLeft:"8px solid transparent",borderRight:"8px solid transparent",borderBottom:"12px solid "+gray17},tailAbove:{bottom:-12,borderBottom:"none",borderTop:"12px solid "+gray17,top:"auto"},tooltipParagraph:{margin:12},warning:{color:warningColor,fontFamily:boldFontFamily},publishBlockingError:{color:publishBlockingErrorColor}});
1633
1634
 
@@ -1666,7 +1667,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
1666
1667
 
1667
1668
  class WidgetContainer extends React.Component{componentDidMount(){if(this.props.widgetProps.apiOptions.isMobile){const containerWidth=ReactDOM__default.findDOMNode(this).offsetWidth;this.setState({sizeClass:getClassFromWidth(containerWidth)});}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.type!==nextProps.type){throw new Error("WidgetContainer can't change widget type; set a different "+"key instead to recreate the container.")}}render(){let className=classNames$1({"perseus-widget-container":true,"widget-highlight":this.props.shouldHighlight,"widget-nohighlight":!this.props.shouldHighlight,"perseus-widget__definition":this.props.type==="definition"});const type=this.props.type;const userAgent=navigator.userAgent;const WidgetType=getWidget(type);if(WidgetType==null){console.warn(`Widget type '${type}' not found!`);return jsxRuntimeExports.jsx("div",{className:className})}let subType="null";if(type==="interactive-graph"){const props=this.props.widgetProps;subType=props.graph?.type??"null";}let alignment=this.props.widgetProps.alignment;if(alignment==="default"){alignment=CoreWidgetRegistry.getDefaultAlignment(type);}className+=" widget-"+alignment;const apiOptions=this.props.widgetProps.apiOptions;const isStatic=this.props.widgetProps.static||apiOptions.readOnly;const staticContainerStyles={position:"relative",overflow:"visible"};const staticOverlayStyles={width:"100%",height:"100%",position:"absolute",top:0,left:0,zIndex:3};const linterContext=isLintable(type)?this.props.linterContext:{...this.props.linterContext,highlightLint:false};return jsxRuntimeExports.jsx("div",{className:className,style:isStatic?staticContainerStyles:{},children:jsxRuntimeExports.jsx(DependenciesContext.Consumer,{children:({analytics})=>jsxRuntimeExports.jsxs(ErrorBoundary,{metadata:{widget_type:type,widget_id:this.props.id},onError:error=>{analytics.onAnalyticsEvent({type:"perseus:widget-rendering-error:ti",payload:{widgetSubType:subType,widgetType:type,widgetId:this.props.id,message:error.message,userAgent:userAgent}});},children:[jsxRuntimeExports.jsx(WidgetType,{...this.props.widgetProps,linterContext:linterContext,containerSizeClass:this.state.sizeClass,ref:this.widgetRef}),isStatic&&jsxRuntimeExports.jsx("div",{style:staticOverlayStyles})]})})})}constructor(...args){super(...args),this.widgetRef=React.createRef(),this.state={sizeClass:containerSizeClass.MEDIUM},this.getWidget=()=>{return this.widgetRef.current};}}WidgetContainer.defaultProps={linterContext:linterContextDefault};
1668
1669
 
1669
- const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return _.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return _.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion(propsA,propsB){function makeItem(props){return splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!_.isEqual(makeItem(propsA),makeItem(propsB))}class Renderer extends React.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!_.isEqual(this.state,nextState);const propsChanged=!_.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];if(!this._interactionTrackers){this._interactionTrackers={};}let interactionTracker=this._interactionTrackers[widgetId];if(!interactionTracker){interactionTracker=this._interactionTrackers[widgetId]=new InteractionTracker(apiOptions.trackInteraction,widgetInfo&&widgetInfo.type,widgetId,getTracking(widgetInfo&&widgetInfo.type));}return {...widgetProps,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,questionCompleted:this.props.questionCompleted,showSolutions:this.props.showSolutions,onFocus:_.partial(this._onWidgetFocus,widgetId),onBlur:_.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.onInteractWithWidget(widgetId);},trackInteraction:interactionTracker.track,isLastUsedWidget:widgetId===this.state.lastUsedWidgetId}}getSerializedState(){return mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}handleStateUpdate(id,cb,silent){this.setState(prevState=>{const lastUsedWidgetId=silent?prevState.lastUsedWidgetId:id;return {lastUsedWidgetId}},()=>{setTimeout(()=>{const cbResult=cb&&cb();if(!silent){this.props.onInteractWithWidget(id);}if(cbResult!==false){this._setCurrentFocus([id]);}},0);});}getUserInput(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInput called without providing userInput to Renderer`)}return this.widgetIds.map(id=>{return userInput[id]})}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}getPromptJSON(){const{content}=this.props;const widgetJSON={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);widgetJSON[id]=widget?.getPromptJSON?.()||{};});return {content,widgets:widgetJSON}}score(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();const content=this.getContent(this.props,this.state);this.widgetIds=[];if(this.shouldRenderJiptPlaceholder(this.props,this.state)){if(!this.translationIndex){this.translationIndex=getDependencies().rendererTranslationComponents.addComponent(this);}if(!apiOptions.isArticle){return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{"data-perseus-component-index":this.translationIndex,children:content})})}}this._isTwoColumn=false;const parsedMarkdown=this.props.inline?PerseusMarkdown.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown.parse(content,{isJipt:this.translationIndex!=null});if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter.runLinter(parsedMarkdown,fullLinterContext,true);this._translationLinter.applyLintErrors(parsedMarkdown,[...this.state.translationLintErrors,...this.props.legacyPerseusLint||[]]);}const markdownContents=this.outputMarkdown(parsedMarkdown,{baseElements:apiOptions.baseElements});const className=classNames$1({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},this._getDefaultWidgetInfo=widgetId=>{const widgetIdParts=Util.rTypeFromWidgetId.exec(widgetId);if(widgetIdParts==null){return {}}return {type:widgetIdParts[1],graded:true,options:{}}},this._getWidgetInfo=widgetId=>{return this.state.widgetInfo[widgetId]||this._getDefaultWidgetInfo(widgetId)},this.renderWidget=(impliedType,id,state)=>{const widgetInfo=this.state.widgetInfo[id];if(widgetInfo&&widgetInfo.alignment==="full-width"){state.foundFullWidth=true;}if(widgetInfo){const type=widgetInfo&&widgetInfo.type||impliedType;const shouldHighlight=_.contains(this.props.highlightedWidgets,id);return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),shouldHighlight:shouldHighlight,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},this.findInternalWidgets=filterCriterion=>{let filterFunc;if(typeof filterCriterion==="string"){if(filterCriterion.indexOf(" ")!==-1){const widgetId=filterCriterion;filterFunc=(id,widgetInfo,widget)=>id===widgetId;}else {const widgetType=filterCriterion;filterFunc=(id,widgetInfo,widget)=>{return widgetInfo.type===widgetType};}}else {filterFunc=filterCriterion;}const results=this.widgetIds.filter(id=>{const widgetInfo=this._getWidgetInfo(id);const widget=this.getWidgetInstance(id);return filterFunc(id,widgetInfo,widget)}).map(this.getWidgetInstance);return results},this.findWidgets=filterCriterion=>{return [...this.findInternalWidgets(filterCriterion),...this.props.findExternalWidgets(filterCriterion)]},this.getWidgetInstance=id=>{const ref=this._widgetContainers.get(makeContainerId(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!_.isArray(focusPath)){throw new PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!_.isEqual(fullPath,blurringFocusPath)){return}_.defer(()=>{if(_.isEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.getContent=(props,state)=>{return state.jiptContent||props.content},this.shouldRenderJiptPlaceholder=(props,state)=>{return getDependencies().JIPT.useJIPT&&state.jiptContent==null&&props.content.indexOf("crwdns")!==-1},this.replaceJiptContent=(content,paragraphIndex)=>{if(paragraphIndex==null){this.setState({jiptContent:content});}else {const codeFenceRegex=/^\s*(`{3,}|~{3,})\s*(\S+)?\s*\n([\s\S]+?)\s*\1\s*$/;if(codeFenceRegex.test(content));else if(/\S\n\s*\n\S/.test(content)){content="$\\large{\\red{\\text{Please translate each "+"paragraph to a single paragraph.}}}$";}else if(/^\s*$/.test(content)){content="$\\large{\\red{\\text{Translated paragraph is "+"currently empty}}}$";}const allContent=this.getContent(this.props,this.state);const paragraphs=JiptParagraphs.parseToArray(allContent);paragraphs[paragraphIndex]=content;this.setState({jiptContent:JiptParagraphs.joinFromArray(paragraphs)});}},this.outputMarkdown=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;state.paragraphIndex=i;const nodeOut=this.outputMarkdown(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}this._foundTextNodes=false;state.foundFullWidth=false;const output=this.outputNested(ast,state);let className;if(this.translationIndex!=null){className=null;}else {className=classNames$1({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,inline:this.props.inline,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;const nodeOut=this.outputNested(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}return this.outputNode(ast,this.outputNested,state)},this.outputNode=(node,nestedOutput,state)=>{const apiOptions=this.getApiOptions();const imagePlaceholder=apiOptions.imagePlaceholder;if(node.type==="widget"){const widgetPlaceholder=apiOptions.widgetPlaceholder;if(widgetPlaceholder){return widgetPlaceholder}this._foundTextNodes=true;if(this.widgetIds.includes(node.id)){return jsxRuntimeExports.jsx("span",{className:"renderer-widget-error",children:["Widget [[","☃"," ",node.id,"]] already exists."].join("")},state.key)}this.widgetIds.push(node.id);return this.renderWidget(node.widgetType,node.id,state)}if(node.type==="blockMath"){const content=preprocessTex(node.content);const innerStyle={overflowX:"auto",overflowY:"hidden",paddingTop:10,paddingBottom:10,marginTop:-10,marginBottom:-10};if(apiOptions.isMobile){const margin=16;const outerStyle={marginLeft:-16,marginRight:-16};const horizontalPadding={paddingLeft:margin,paddingRight:margin};const mobileInnerStyle={...innerStyle,...styles$F.mobileZoomableParentFix};return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",style:outerStyle,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:{...mobileInnerStyle,...horizontalPadding},children:jsxRuntimeExports.jsx(ZoomableTeX,{children:content})})})},state.key)}return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:innerStyle,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{setAssetStatus:setAssetStatus,children:content})})})})},state.key)}if(node.type==="math"){const tex=node.content;return jsxRuntimeExports.jsx("span",{style:{whiteSpace:"nowrap"},children:jsxRuntimeExports.jsxs(ErrorBoundary,{children:[jsxRuntimeExports.jsx("span",{}),jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{onRender:this.props.onRender,setAssetStatus:setAssetStatus,children:tex})}),jsxRuntimeExports.jsx("span",{})]})},state.key)}if(node.type==="image"){if(imagePlaceholder){return imagePlaceholder}const extraAttrs=_.has(this.props.images,node.target)?this.props.images[node.target]:null;const responsive=!state.inTable;return jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{setAssetStatus:setAssetStatus,src:PerseusMarkdown.sanitizeUrl(node.target),alt:node.alt,title:node.title,responsive:responsive,onUpdate:this.props.onRender,zoomToFullSizeOnMobile:apiOptions.isMobile&&apiOptions.isArticle,...extraAttrs})})},state.key)}if(node.type==="columns"){this._isTwoColumn=true;return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown.ruleOutput(node,nestedOutput,{...state,isMobile:apiOptions.isMobile,inTable:true});if(!apiOptions.isMobile){return output}const outerStyle={marginLeft:-16,marginRight:-16};const innerStyle={paddingLeft:0,paddingRight:0};const mobileInnerStyle={...innerStyle,...styles$F.mobileZoomableParentFix};const wrappedOutput=jsxRuntimeExports.jsx("div",{style:{...mobileInnerStyle,overflowX:"auto"},children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(Zoomable,{animateHeight:true,children:output})})});return jsxRuntimeExports.jsx("div",{style:outerStyle,children:wrappedOutput})}return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender||oldOnRender!==noopOnRender){const $images=$(ReactDOM__default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender){$images.off("load",oldOnRender);}if(onRender!==noopOnRender){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix(path,this._currentFocus)){const prevFocus=this._currentFocus;if(prevFocus){this.blurPath(prevFocus);}this._currentFocus=path;apiOptions.onFocusChange(this._currentFocus,prevFocus);}},this.focus=()=>{let id;let focusResult;for(let i=0;i<this.widgetIds.length;i++){const widgetId=this.widgetIds[i];const widget=this.getWidgetInstance(widgetId);const widgetFocusResult=widget?.focus?.();if(widgetFocusResult){id=widgetId;focusResult=widgetFocusResult;break}}if(id){let path;if(typeof focusResult==="object"){path=[id].concat(focusResult.path||[]);Log.error("Renderer received a focus result of type 'object' "+"instead of the expected type 'boolean'",Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){return ReactDOM__default.findDOMNode(widget)}},this.getInputPaths=()=>{const inputPaths=[];this.widgetIds.forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getInputPaths){const widgetInputPaths=widget.getInputPaths();widgetInputPaths.forEach(inputPath=>{const relativeInputPath=[widgetId].concat(inputPath);inputPaths.push(relativeInputPath);});}});return inputPaths},this.focusPath=path=>{if(_.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!_.isEqual(this._currentFocus,path)){return}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget){const blurWidget=this.getWidgetInstance(widgetId);blurWidget?.blurInputPath?.(interWidgetPath);}},this.blur=()=>{if(this._currentFocus){this.blurPath(this._currentFocus);}},this.serialize=()=>{const state={};_.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!_.isEmpty(s)){state[id]=s;}},this);return state},this.getWidgetIds=()=>{return this.widgetIds},this.handletranslationLintErrors=lintErrors=>{if(!this._isMounted){return}this.setState({translationLintErrors:lintErrors});};this._translationLinter=new TranslationLinter;this.state={jiptContent:null,translationLintErrors:[],lastUsedWidgetId:null,...this._getInitialWidgetState(props)};}}Renderer.contextType=PerseusI18nContext;Renderer.defaultProps={content:"",widgets:{},images:{},highlightedWidgets:[],questionCompleted:false,showSolutions:"none",onRender:noopOnRender,onInteractWithWidget:function(){},findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter.linterContextDefault};const styles$F={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
1670
+ const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return _.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return _.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion(propsA,propsB){function makeItem(props){return splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!_.isEqual(makeItem(propsA),makeItem(propsB))}class Renderer extends React.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!_.isEqual(this.state,nextState);const propsChanged=!_.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];if(!this._interactionTrackers){this._interactionTrackers={};}let interactionTracker=this._interactionTrackers[widgetId];if(!interactionTracker){interactionTracker=this._interactionTrackers[widgetId]=new InteractionTracker(apiOptions.trackInteraction,widgetInfo&&widgetInfo.type,widgetId,getTracking(widgetInfo&&widgetInfo.type));}return {...widgetProps,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,questionCompleted:this.props.questionCompleted,showSolutions:this.props.showSolutions,onFocus:_.partial(this._onWidgetFocus,widgetId),onBlur:_.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.onInteractWithWidget(widgetId);},trackInteraction:interactionTracker.track}}getSerializedState(){return mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}handleStateUpdate(id,cb,silent){setTimeout(()=>{const cbResult=cb&&cb();if(!silent){this.props.onInteractWithWidget(id);}if(cbResult!==false){this._setCurrentFocus([id]);}},0);}getUserInput(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInput called without providing userInput to Renderer`)}return this.widgetIds.map(id=>{return userInput[id]})}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}getPromptJSON(){const{content}=this.props;const widgetJSON={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);widgetJSON[id]=widget?.getPromptJSON?.()||{};});return {content,widgets:widgetJSON}}score(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();const content=this.getContent(this.props,this.state);this.widgetIds=[];if(this.shouldRenderJiptPlaceholder(this.props,this.state)){if(!this.translationIndex){this.translationIndex=getDependencies().rendererTranslationComponents.addComponent(this);}if(!apiOptions.isArticle){return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{"data-perseus-component-index":this.translationIndex,children:content})})}}this._isTwoColumn=false;const parsedMarkdown=this.props.inline?PerseusMarkdown.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown.parse(content,{isJipt:this.translationIndex!=null});if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter.runLinter(parsedMarkdown,fullLinterContext,true);this._translationLinter.applyLintErrors(parsedMarkdown,[...this.state.translationLintErrors,...this.props.legacyPerseusLint||[]]);}const markdownContents=this.outputMarkdown(parsedMarkdown,{baseElements:apiOptions.baseElements});const className=classNames$1({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},this._getDefaultWidgetInfo=widgetId=>{const widgetIdParts=Util.rTypeFromWidgetId.exec(widgetId);if(widgetIdParts==null){return {}}return {type:widgetIdParts[1],graded:true,options:{}}},this._getWidgetInfo=widgetId=>{return this.state.widgetInfo[widgetId]||this._getDefaultWidgetInfo(widgetId)},this.renderWidget=(impliedType,id,state)=>{const widgetInfo=this.state.widgetInfo[id];if(widgetInfo&&widgetInfo.alignment==="full-width"){state.foundFullWidth=true;}if(widgetInfo){const type=widgetInfo&&widgetInfo.type||impliedType;const shouldHighlight=_.contains(this.props.highlightedWidgets,id);return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),shouldHighlight:shouldHighlight,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},this.findInternalWidgets=filterCriterion=>{let filterFunc;if(typeof filterCriterion==="string"){if(filterCriterion.indexOf(" ")!==-1){const widgetId=filterCriterion;filterFunc=(id,widgetInfo,widget)=>id===widgetId;}else {const widgetType=filterCriterion;filterFunc=(id,widgetInfo,widget)=>{return widgetInfo.type===widgetType};}}else {filterFunc=filterCriterion;}const results=this.widgetIds.filter(id=>{const widgetInfo=this._getWidgetInfo(id);const widget=this.getWidgetInstance(id);return filterFunc(id,widgetInfo,widget)}).map(this.getWidgetInstance);return results},this.findWidgets=filterCriterion=>{return [...this.findInternalWidgets(filterCriterion),...this.props.findExternalWidgets(filterCriterion)]},this.getWidgetInstance=id=>{const ref=this._widgetContainers.get(makeContainerId(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!_.isArray(focusPath)){throw new PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!_.isEqual(fullPath,blurringFocusPath)){return}_.defer(()=>{if(_.isEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.getContent=(props,state)=>{return state.jiptContent||props.content},this.shouldRenderJiptPlaceholder=(props,state)=>{return getDependencies().JIPT.useJIPT&&state.jiptContent==null&&props.content.indexOf("crwdns")!==-1},this.replaceJiptContent=(content,paragraphIndex)=>{if(paragraphIndex==null){this.setState({jiptContent:content});}else {const codeFenceRegex=/^\s*(`{3,}|~{3,})\s*(\S+)?\s*\n([\s\S]+?)\s*\1\s*$/;if(codeFenceRegex.test(content));else if(/\S\n\s*\n\S/.test(content)){content="$\\large{\\red{\\text{Please translate each "+"paragraph to a single paragraph.}}}$";}else if(/^\s*$/.test(content)){content="$\\large{\\red{\\text{Translated paragraph is "+"currently empty}}}$";}const allContent=this.getContent(this.props,this.state);const paragraphs=JiptParagraphs.parseToArray(allContent);paragraphs[paragraphIndex]=content;this.setState({jiptContent:JiptParagraphs.joinFromArray(paragraphs)});}},this.outputMarkdown=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;state.paragraphIndex=i;const nodeOut=this.outputMarkdown(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}this._foundTextNodes=false;state.foundFullWidth=false;const output=this.outputNested(ast,state);let className;if(this.translationIndex!=null){className=null;}else {className=classNames$1({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,inline:this.props.inline,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;const nodeOut=this.outputNested(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}return this.outputNode(ast,this.outputNested,state)},this.outputNode=(node,nestedOutput,state)=>{const apiOptions=this.getApiOptions();const imagePlaceholder=apiOptions.imagePlaceholder;if(node.type==="widget"){const widgetPlaceholder=apiOptions.widgetPlaceholder;if(widgetPlaceholder){return widgetPlaceholder}this._foundTextNodes=true;if(this.widgetIds.includes(node.id)){return jsxRuntimeExports.jsx("span",{className:"renderer-widget-error",children:["Widget [[","☃"," ",node.id,"]] already exists."].join("")},state.key)}this.widgetIds.push(node.id);return this.renderWidget(node.widgetType,node.id,state)}if(node.type==="blockMath"){const content=preprocessTex(node.content);const innerStyle={overflowX:"auto",overflowY:"hidden",paddingTop:10,paddingBottom:10,marginTop:-10,marginBottom:-10};if(apiOptions.isMobile){const margin=16;const outerStyle={marginLeft:-16,marginRight:-16};const horizontalPadding={paddingLeft:margin,paddingRight:margin};const mobileInnerStyle={...innerStyle,...styles$F.mobileZoomableParentFix};return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",style:outerStyle,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:{...mobileInnerStyle,...horizontalPadding},children:jsxRuntimeExports.jsx(ZoomableTeX,{children:content})})})},state.key)}return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:innerStyle,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{setAssetStatus:setAssetStatus,children:content})})})})},state.key)}if(node.type==="math"){const tex=node.content;return jsxRuntimeExports.jsx("span",{style:{whiteSpace:"nowrap"},children:jsxRuntimeExports.jsxs(ErrorBoundary,{children:[jsxRuntimeExports.jsx("span",{}),jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{onRender:this.props.onRender,setAssetStatus:setAssetStatus,children:tex})}),jsxRuntimeExports.jsx("span",{})]})},state.key)}if(node.type==="image"){if(imagePlaceholder){return imagePlaceholder}const extraAttrs=_.has(this.props.images,node.target)?this.props.images[node.target]:null;const responsive=!state.inTable;return jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{setAssetStatus:setAssetStatus,src:PerseusMarkdown.sanitizeUrl(node.target),alt:node.alt,title:node.title,responsive:responsive,onUpdate:this.props.onRender,zoomToFullSizeOnMobile:apiOptions.isMobile&&apiOptions.isArticle,...extraAttrs})})},state.key)}if(node.type==="columns"){this._isTwoColumn=true;return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown.ruleOutput(node,nestedOutput,{...state,isMobile:apiOptions.isMobile,inTable:true});if(!apiOptions.isMobile){return output}const outerStyle={marginLeft:-16,marginRight:-16};const innerStyle={paddingLeft:0,paddingRight:0};const mobileInnerStyle={...innerStyle,...styles$F.mobileZoomableParentFix};const wrappedOutput=jsxRuntimeExports.jsx("div",{style:{...mobileInnerStyle,overflowX:"auto"},children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(Zoomable,{animateHeight:true,children:output})})});return jsxRuntimeExports.jsx("div",{style:outerStyle,children:wrappedOutput})}return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender||oldOnRender!==noopOnRender){const $images=$(ReactDOM__default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender){$images.off("load",oldOnRender);}if(onRender!==noopOnRender){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix(path,this._currentFocus)){const prevFocus=this._currentFocus;if(prevFocus){this.blurPath(prevFocus);}this._currentFocus=path;apiOptions.onFocusChange(this._currentFocus,prevFocus);}},this.focus=()=>{let id;let focusResult;for(let i=0;i<this.widgetIds.length;i++){const widgetId=this.widgetIds[i];const widget=this.getWidgetInstance(widgetId);const widgetFocusResult=widget?.focus?.();if(widgetFocusResult){id=widgetId;focusResult=widgetFocusResult;break}}if(id){let path;if(typeof focusResult==="object"){path=[id].concat(focusResult.path||[]);Log.error("Renderer received a focus result of type 'object' "+"instead of the expected type 'boolean'",Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){return ReactDOM__default.findDOMNode(widget)}},this.getInputPaths=()=>{const inputPaths=[];this.widgetIds.forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getInputPaths){const widgetInputPaths=widget.getInputPaths();widgetInputPaths.forEach(inputPath=>{const relativeInputPath=[widgetId].concat(inputPath);inputPaths.push(relativeInputPath);});}});return inputPaths},this.focusPath=path=>{if(_.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!_.isEqual(this._currentFocus,path)){return}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget){const blurWidget=this.getWidgetInstance(widgetId);blurWidget?.blurInputPath?.(interWidgetPath);}},this.blur=()=>{if(this._currentFocus){this.blurPath(this._currentFocus);}},this.serialize=()=>{const state={};_.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!_.isEmpty(s)){state[id]=s;}},this);return state},this.getWidgetIds=()=>{return this.widgetIds},this.handletranslationLintErrors=lintErrors=>{if(!this._isMounted){return}this.setState({translationLintErrors:lintErrors});};this._translationLinter=new TranslationLinter;this.state={jiptContent:null,translationLintErrors:[],...this._getInitialWidgetState(props)};}}Renderer.contextType=PerseusI18nContext;Renderer.defaultProps={content:"",widgets:{},images:{},highlightedWidgets:[],questionCompleted:false,showSolutions:"none",onRender:noopOnRender,onInteractWithWidget:function(){},findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter.linterContextDefault};const styles$F={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
1670
1671
 
1671
1672
  const{captureScratchpadTouchStart: captureScratchpadTouchStart$2}=Util;const InputWithExamples=forwardRef(function InputWithExamples({shouldShowExamples=true,onFocus=()=>{},onBlur=()=>{},disabled=false,linterContext=PerseusLinter.linterContextDefault,className="",...props},ref){const context=React.useContext(PerseusI18nContext);const inputRef=React.useRef(null);const[inputFocused,setInputFocused]=React.useState(false);const id=useId();const ariaId=`aria-for-${id}`;useImperativeHandle(ref,()=>({current:inputRef.current,focus:()=>{if(inputRef.current){inputRef.current.focus();}},blur:()=>{if(inputRef.current){inputRef.current.blur();}}}));const getInputClassName=()=>{let inputClassName=ClassNames.INPUT;if(inputFocused){inputClassName+=" "+ClassNames.FOCUSED;}if(className){inputClassName+=" "+className;}return inputClassName};const handleFocus=()=>{onFocus();setInputFocused(true);};const handleBlur=()=>{onBlur();setInputFocused(false);};const renderInput=()=>{const examplesAria=shouldShowExamples?`${props.examples[0]}
1672
1673
  ${props.examples.slice(1).join(", or\n")}`.replace(/\*/g,"").replace(/\$/g,"").replace(/\\ \\text{pi}/g," pi").replace(/\\ /g," and "):"";const inputProps={id:id,"aria-describedby":shouldShowExamples?ariaId:undefined,ref:inputRef,className:getInputClassName(),labelText:props.labelText,value:props.value,onFocus:handleFocus,onBlur:handleBlur,disabled:disabled,style:props.style,onChange:props.onChange,onTouchStart:captureScratchpadTouchStart$2,autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:"false"};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(TextInput,{...inputProps}),jsxRuntimeExports.jsx("span",{id:ariaId,style:{display:"none"},children:examplesAria})]})};const renderTooltipContent=()=>{return jsxRuntimeExports.jsx(TooltipContent,{children:jsxRuntimeExports.jsx("div",{id:id,className:"input-with-examples-tooltip",children:jsxRuntimeExports.jsx(Renderer,{content:examplesContent,linterContext:PerseusLinter.pushContextStack(linterContext,"input-with-examples"),strings:context.strings})})})};const examplesContent=props.examples.length<=2?props.examples.join(" "):props.examples.map((example,index)=>{return index===0&&example.startsWith("**")?`${example}
@@ -1702,7 +1703,7 @@ function getChoiceLetter(pos,strings){const lettersString=strings.letters;const
1702
1703
 
1703
1704
  const getInstructionsText$1=({multipleSelect,countChoices,numCorrect,strings})=>{if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer};
1704
1705
 
1705
- const MultipleChoiceComponent=({choices,countChoices,multipleSelect=false,numCorrect,onChoiceChange,reviewMode})=>{const{strings}=usePerseusI18n();const legendId=useId();const instructions=getInstructionsText$1({multipleSelect,countChoices,numCorrect,strings});const choiceListClasses=reviewMode?`${styles$A.choiceList} ${styles$A.reviewAnswers}`:styles$A.choiceList;const scrollId=useId()+"-scroll";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("fieldset",{className:styles$A.container,"data-feature-flag":"feature flag is ON",children:[jsxRuntimeExports.jsx("legend",{id:legendId,"aria-hidden":"true",className:styles$A.instructions,children:instructions}),jsxRuntimeExports.jsx(ScrollableView,{id:scrollId,overflowX:"auto",children:jsxRuntimeExports.jsx("ul",{"aria-labelledby":legendId,className:choiceListClasses,children:jsxRuntimeExports.jsx(ChoiceListItems,{choices:choices,i18nStrings:strings,onChoiceChange:onChoiceChange,reviewMode:reviewMode,multipleSelect:multipleSelect})})})]}),jsxRuntimeExports.jsx(ScrollableView.Controls,{target:scrollId})]})};const ChoiceListItems=props=>{const{choices,i18nStrings,multipleSelect,onChoiceChange,reviewMode}=props;const listId=useId();const items=choices.map((choice,i)=>{const updateChecked=isChecked=>{onChoiceChange(choice.id,isChecked);};const contentId=`${listId}-choice-${i+1}`;const choiceLetter=getChoiceLetter(i,i18nStrings);const srContent=reviewMode&&choice.correct?i18nStrings.choiceCorrect:i18nStrings.choice;const indicatorContent={visible:choiceLetter,screenReader:srContent({letter:choiceLetter}),labelledBy:contentId};const showCorrectness=reviewMode?choice.correct?"correct":"wrong":undefined;const content=choice.isNoneOfTheAbove?i18nStrings.noneOfTheAbove:choice.content;let rationale;if(reviewMode&&choice.hasRationale){const rationaleId=`${contentId}-rationale`;indicatorContent.describedBy=rationaleId;const rationaleClasses=showCorrectness==="correct"?`${styles$A.rationale} ${styles$A.isCorrect}`:styles$A.rationale;rationale=jsxRuntimeExports.jsx("div",{id:rationaleId,className:rationaleClasses,children:choice.rationale});}return jsxRuntimeExports.jsx(Choice$2,{checked:choice.checked,indicatorContent:indicatorContent,isMultiSelect:multipleSelect,showCorrectness:showCorrectness,updateChecked:updateChecked,children:jsxRuntimeExports.jsxs("div",{className:styles$A.content,children:[jsxRuntimeExports.jsx("div",{id:contentId,children:content}),rationale]})},choice.id)});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:items})};
1706
+ const MultipleChoiceComponent=({choices,countChoices,multipleSelect=false,numCorrect,onChoiceChange,reviewMode})=>{const{strings}=usePerseusI18n();const legendId=useId();const containerRef=useRef(null);const[backgroundColor,setBackgroundColor]=useState("transparent");useEffect(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},[]);useTimeout(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},100);const instructions=getInstructionsText$1({multipleSelect,countChoices,numCorrect,strings});const choiceListClasses=reviewMode?`${styles$A.choiceList} ${styles$A.reviewAnswers}`:styles$A.choiceList;const cssVariableDeclaration=backgroundColor!=="transparent"?{"--perseus-widget-background-color":backgroundColor}:undefined;const scrollId=useId()+"-scroll";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("fieldset",{className:styles$A.container,"data-feature-flag":"feature flag is ON",ref:containerRef,style:cssVariableDeclaration,children:[jsxRuntimeExports.jsx("legend",{id:legendId,"aria-hidden":"true",className:styles$A.instructions,children:instructions}),jsxRuntimeExports.jsx(ScrollableView,{id:scrollId,overflowX:"auto",children:jsxRuntimeExports.jsx("ul",{"aria-labelledby":legendId,className:choiceListClasses,children:jsxRuntimeExports.jsx(ChoiceListItems,{choices:choices,i18nStrings:strings,onChoiceChange:onChoiceChange,reviewMode:reviewMode,multipleSelect:multipleSelect})})})]}),jsxRuntimeExports.jsx(ScrollableView.Controls,{target:scrollId})]})};const ChoiceListItems=props=>{const{choices,i18nStrings,multipleSelect,onChoiceChange,reviewMode}=props;const listId=useId();const items=choices.map((choice,i)=>{const updateChecked=isChecked=>{onChoiceChange(choice.id,isChecked);};const contentId=`${listId}-choice-${i+1}`;const choiceLetter=getChoiceLetter(i,i18nStrings);const srContent=reviewMode&&choice.correct?i18nStrings.choiceCorrect:i18nStrings.choice;const indicatorContent={visible:choiceLetter,screenReader:srContent({letter:choiceLetter}),labelledBy:contentId};const showCorrectness=reviewMode?choice.correct?"correct":"wrong":undefined;const content=choice.isNoneOfTheAbove?i18nStrings.noneOfTheAbove:choice.content;let rationale;if(reviewMode&&choice.hasRationale){const rationaleId=`${contentId}-rationale`;indicatorContent.describedBy=rationaleId;const rationaleClasses=showCorrectness==="correct"?`${styles$A.rationale} ${styles$A.isCorrect}`:styles$A.rationale;rationale=jsxRuntimeExports.jsx("div",{id:rationaleId,className:rationaleClasses,children:choice.rationale});}return jsxRuntimeExports.jsx(Choice$2,{checked:choice.checked,indicatorContent:indicatorContent,isMultiSelect:multipleSelect,showCorrectness:showCorrectness,updateChecked:updateChecked,children:jsxRuntimeExports.jsxs("div",{className:styles$A.content,children:[jsxRuntimeExports.jsx("div",{id:contentId,children:content}),rationale]})},choice.id)});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:items})};
1706
1707
 
1707
1708
  const getPromptJSON$p=widgetData=>{return {type:"passage-ref",options:{passageNumber:widgetData.passageNumber,referenceNumber:widgetData.referenceNumber,summaryText:widgetData.summaryText??""}}};
1708
1709
 
@@ -1758,9 +1759,9 @@ const intermediateCheckboxPadding=`16px 16px`;const intermediateCheckboxPaddingP
1758
1759
 
1759
1760
  const ChoiceNoneAbove=function({content,forwardedRef,showContent=true,...rest}){const{strings}=usePerseusI18n();const choiceProps={...rest,content:showContent?content:jsxRuntimeExports.jsx(Renderer,{content:strings.noneOfTheAbove,strings:strings},"noneOfTheAboveRenderer")};return jsxRuntimeExports.jsx(Choice$1,{...choiceProps,ref:forwardedRef})};var ChoiceNoneAbove$1 = React.forwardRef(function ChoiceNoneAboveWithRef(props,ref){return jsxRuntimeExports.jsx(ChoiceNoneAbove,{...props,forwardedRef:ref})});
1760
1761
 
1761
- const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;function getInstructionsText(multipleSelect,countChoices,numCorrect,strings){if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer}const BaseRadio=function({apiOptions,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,isLastUsedWidget,onChange,registerFocusFunction}){const{strings}=usePerseusI18n();const prevReviewMode=useRef();const choiceRefs=useRef([]);useEffect(()=>{if(apiOptions.canScrollPage&&isLastUsedWidget&&reviewMode&&prevReviewMode.current!=null){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewMode.current=reviewMode;},[apiOptions,choices,isLastUsedWidget,reviewMode]);function updateChoice(choiceId,checked){const checkedChoiceIds=[];if(checked&&!multipleSelect){checkedChoiceIds.push(choiceId);}else if(checked&&multipleSelect){const currentCheckedIds=choices.filter(choice=>choice.checked).map(choice=>choice.id);checkedChoiceIds.push(...currentCheckedIds,choiceId);}else {const currentCheckedIds=choices.filter(choice=>choice.checked&&choice.id!==choiceId).map(choice=>choice.id);checkedChoiceIds.push(...currentCheckedIds);}onChange(checkedChoiceIds);}registerFocusFunction?.(choiceIndex=>{const ref=choiceRefs.current[choiceIndex||0];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){buttonNode.focus();}else {return false}return true});const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames$1("perseus-widget-radio",!editMode&&"perseus-rendered-radio",css(styles$q.radio,styles$q.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$q.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$q.radioContainerLastHighlighted));const instructionsClassName=classNames$1("instructions",css(styles$q.instructions,isMobile&&styles$q.instructionsMobile));const instructions=getInstructionsText(multipleSelect,countChoices,numCorrect,strings);const responsiveClassName=css(styles$q.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx("ul",{className:className,style:{listStyle:"none"},children:choices.map((choice,i)=>{let Element=Choice$1;const ref=React.createRef();choiceRefs.current[i]=ref;const elementProps={id:choice.id,apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(choice.id,newValues.checked);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove$1;_.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=!!nextChoice&&nextChoice.highlighted;const aphroditeClassName=checked=>{return css(styles$q.item,styles$q.responsiveItem,checked&&styles$q.selectedItem,checked&&choice.highlighted&&styles$q.aboveBackdrop,checked&&choice.highlighted&&apiOptions.isMobile&&styles$q.aboveBackdropMobile,nextChoiceHighlighted&&apiOptions.isMobile&&styles$q.nextHighlighted)};aphroditeClassName(true);let correctnessClass;if(reviewMode){correctnessClass=choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames$1(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(choice.id,!choice.checked);return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$1,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},choice.id)})})]});return jsxRuntimeExports.jsx("div",{className:css(styles$q.responsiveContainer),children:fieldset})};const styles$q=StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,width:"auto",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1762
+ const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;function getInstructionsText(multipleSelect,countChoices,numCorrect,strings){if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer}const BaseRadio=function({apiOptions,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,onChange,registerFocusFunction}){const{strings}=usePerseusI18n();const prevReviewMode=useRef();const choiceRefs=useRef([]);useEffect(()=>{if(apiOptions.canScrollPage&&reviewMode&&prevReviewMode.current!=null){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewMode.current=reviewMode;},[apiOptions,choices,reviewMode]);function updateChoice(choiceId,checked){const checkedChoiceIds=[];if(checked&&!multipleSelect){checkedChoiceIds.push(choiceId);}else if(checked&&multipleSelect){const currentCheckedIds=choices.filter(choice=>choice.checked).map(choice=>choice.id);checkedChoiceIds.push(...currentCheckedIds,choiceId);}else {const currentCheckedIds=choices.filter(choice=>choice.checked&&choice.id!==choiceId).map(choice=>choice.id);checkedChoiceIds.push(...currentCheckedIds);}onChange(checkedChoiceIds);}registerFocusFunction?.(choiceIndex=>{const ref=choiceRefs.current[choiceIndex||0];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){buttonNode.focus();}else {return false}return true});const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames$1("perseus-widget-radio",!editMode&&"perseus-rendered-radio",css(styles$q.radio,styles$q.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$q.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$q.radioContainerLastHighlighted));const instructionsClassName=classNames$1("instructions",css(styles$q.instructions,isMobile&&styles$q.instructionsMobile));const instructions=getInstructionsText(multipleSelect,countChoices,numCorrect,strings);const responsiveClassName=css(styles$q.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx("ul",{className:className,style:{listStyle:"none"},children:choices.map((choice,i)=>{let Element=Choice$1;const ref=React.createRef();choiceRefs.current[i]=ref;const elementProps={id:choice.id,apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(choice.id,newValues.checked);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove$1;_.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=!!nextChoice&&nextChoice.highlighted;const aphroditeClassName=checked=>{return css(styles$q.item,styles$q.responsiveItem,checked&&styles$q.selectedItem,checked&&choice.highlighted&&styles$q.aboveBackdrop,checked&&choice.highlighted&&apiOptions.isMobile&&styles$q.aboveBackdropMobile,nextChoiceHighlighted&&apiOptions.isMobile&&styles$q.nextHighlighted)};aphroditeClassName(true);let correctnessClass;if(reviewMode){correctnessClass=choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames$1(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(choice.id,!choice.checked);return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$1,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},choice.id)})})]});return jsxRuntimeExports.jsx("div",{className:css(styles$q.responsiveContainer),children:fieldset})};const styles$q=StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,width:"auto",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1762
1763
 
1763
- let Radio$2 = class Radio extends React.Component{focus(choiceIndex){if(this.focusFunction){return this.focusFunction(choiceIndex)}return false}registerFocusFunction(fun){this.focusFunction=fun;}getPromptJSON(){return getPromptJSON$q(this.props,this.props.userInput)}render(){const{choices}=this.props;const{strings}=this.context;let choiceStates;if(this.props.static){choiceStates=choices.map(choice=>({selected:!!choice.correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.showSolutions==="all"){choiceStates=choices.map(({correct})=>({selected:!!correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.choiceStates){choiceStates=this.props.choiceStates;}else {choiceStates=choices.map(()=>({selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}const choicesProp=choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];return {id:choice.id,content:this._renderRenderer(content),checked:selected,correct:!!choice.correct,disabled:readOnly,hasRationale:!!choice.rationale,rationale:this._renderRenderer(choice.rationale),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(this.props.questionCompleted&&selected),highlighted,previouslyAnswered:previouslyAnswered}});return jsxRuntimeExports.jsx(BaseRadio,{labelWrap:true,multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:this.props.numCorrect,choices:choicesProp,onChange:this.updateChoices,reviewMode:this.props.reviewMode,deselectEnabled:this.props.deselectEnabled,apiOptions:this.props.apiOptions,isLastUsedWidget:this.props.isLastUsedWidget,registerFocusFunction:i=>this.registerFocusFunction(i)})}constructor(...args){super(...args),this._renderRenderer=(content="")=>{let nextPassageRefId=1;const widgets={};const modContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(match,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;widgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return jsxRuntimeExports.jsx(Renderer,{content:modContent,widgets:widgets,findExternalWidgets:this.props.findWidgets,alwaysUpdate:true,linterContext:{...this.props.linterContext,blockHighlight:true},strings:this.context.strings},"choiceContentRenderer")},this.updateChoices=checkedChoiceIds=>{const{choiceStates,choices}=this.props;const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{const choiceId=choices[i].id;choiceState.selected=checkedChoiceIds.includes(choiceId);});this.props.onChange({choiceStates:newChoiceStates});this.props.trackInteraction();};}};Radio$2.contextType=PerseusI18nContext;Radio$2.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:linterContextDefault,showSolutions:"none"};
1764
+ let Radio$2 = class Radio extends React.Component{focus(choiceIndex){if(this.focusFunction){return this.focusFunction(choiceIndex)}return false}registerFocusFunction(fun){this.focusFunction=fun;}getPromptJSON(){return getPromptJSON$q(this.props,this.props.userInput)}render(){const{choices}=this.props;const{strings}=this.context;let choiceStates;if(this.props.static){choiceStates=choices.map(choice=>({selected:!!choice.correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.showSolutions==="all"){choiceStates=choices.map(({correct})=>({selected:!!correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.choiceStates){choiceStates=this.props.choiceStates;}else {choiceStates=choices.map(()=>({selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}const choicesProp=choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];return {id:choice.id,content:this._renderRenderer(content),checked:selected,correct:!!choice.correct,disabled:readOnly,hasRationale:!!choice.rationale,rationale:this._renderRenderer(choice.rationale),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(this.props.questionCompleted&&selected),highlighted,previouslyAnswered:previouslyAnswered}});return jsxRuntimeExports.jsx(BaseRadio,{labelWrap:true,multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:this.props.numCorrect,choices:choicesProp,onChange:this.updateChoices,reviewMode:this.props.reviewMode,deselectEnabled:this.props.deselectEnabled,apiOptions:this.props.apiOptions,registerFocusFunction:i=>this.registerFocusFunction(i)})}constructor(...args){super(...args),this._renderRenderer=(content="")=>{let nextPassageRefId=1;const widgets={};const modContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(match,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;widgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return jsxRuntimeExports.jsx(Renderer,{content:modContent,widgets:widgets,findExternalWidgets:this.props.findWidgets,alwaysUpdate:true,linterContext:{...this.props.linterContext,blockHighlight:true},strings:this.context.strings},"choiceContentRenderer")},this.updateChoices=checkedChoiceIds=>{const{choiceStates,choices}=this.props;const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{const choiceId=choices[i].id;choiceState.selected=checkedChoiceIds.includes(choiceId);});this.props.onChange({choiceStates:newChoiceStates});this.props.trackInteraction();};}};Radio$2.contextType=PerseusI18nContext;Radio$2.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:linterContextDefault,showSolutions:"none"};
1764
1765
 
1765
1766
  function initChoiceStates(choices){return choices.map(()=>({highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}))}let Radio$1 = class Radio extends Radio$2{UNSAFE_componentWillUpdate(nextProps){if(!_.isEqual(nextProps.choices,this.props.choices)){this.setState({choiceStates:initChoiceStates(nextProps.choices)});}}getSerializedState(){const{userInput:_,randomize:__,...rest}=this._mergePropsAndState();return {...rest,hasNoneOfTheAbove:rest.hasNoneOfTheAbove??false}}getPromptJSON(){return this.radioRef.current.getPromptJSON()}_handleChange(arg){const newChoiceStates=arg.choiceStates;if(newChoiceStates){this.setState({choiceStates:newChoiceStates.map(choiceState=>{const{selected:_,...rest}=choiceState;return {...rest}})},()=>{const props=this._mergePropsAndState();const mergedProps={...props,choiceStates:deepClone(props.choiceStates||[]).map((choiceState,index)=>{return {...choiceState,selected:newChoiceStates[index].selected}})};const unshuffledUserInput=getUserInputFromSerializedState$f(mergedProps);this.props.handleUserInput(unshuffledUserInput);});}else {throw new Error("unhandled onChange call in Radio!")}}_mergePropsAndState(){const randomSeed=(this.props.problemNum??0)+(this.props.widgetIndex??0);const choices=[...choiceTransform(this.props.choices,this.props.randomize,this.context.strings,randomSeed)];return {...this.props,choices,choiceStates:this.state.choiceStates?.map((choiceState,index)=>{const choice=choices[index];const selected=this.props.userInput?.selectedChoiceIds.includes(choice.id)??false;return {...choiceState,selected}}),onChange:arg=>this._handleChange(arg)}}focus(choiceIndex){if(this.radioRef.current?.focus){return this.radioRef.current.focus(choiceIndex)}return false}render(){const props=this._mergePropsAndState();return this.ffIsOn?jsxRuntimeExports.jsx(Radio$3,{ref:this.radioRef,...props}):jsxRuntimeExports.jsx(Radio$2,{ref:this.radioRef,...props})}constructor(props){super(props),this.ffIsOn=false,this.radioRef=React.createRef(),this.state={choiceStates:[]};this.ffIsOn=props.apiOptions.flags?.["new-radio-widget"]??false;this.state={choiceStates:initChoiceStates(props.choices)};}};
1766
1767
 
@@ -1812,7 +1813,7 @@ const GRADING_STATUSES={ungraded:"ungraded",correct:"correct",incorrect:"incorre
1812
1813
 
1813
1814
  const getPromptJSON$h=(widgetData,activeGroupJSON)=>{return {type:"graded-group-set",options:{groupCount:widgetData.gradedGroups.length,currentGroup:activeGroupJSON}}};
1814
1815
 
1815
- class Indicators extends React.Component{render(){return jsxRuntimeExports.jsx("ul",{className:classNames$1(css(styles$i.indicatorContainer),"indicatorContainer"),children:this.props.gradedGroups.map(({title},i)=>jsxRuntimeExports.jsx("li",{className:css(styles$i.indicator),children:jsxRuntimeExports.jsx(Clickable,{role:"button","aria-label":this.context.strings.skipToTitle({title}),style:styles$i.indicatorButton,onClick:()=>this.props.onChangeCurrentGroup(i),onKeyDown:e=>this.handleKeyDown(e,i),children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(View,{style:[styles$i.indicatorDot,(hovered||focused||pressed)&&styles$i.indicatorDotFocused],children:i===this.props.currentGroup&&jsxRuntimeExports.jsx(View,{style:styles$i.indicatorDotActive,children:jsxRuntimeExports.jsx("span",{className:css(a11y.srOnly),children:this.context.strings.current})})})})},title))})}constructor(...args){super(...args),this.handleKeyDown=(e,i)=>{if(e.key==="Enter"||e.key===" "){this.props.onChangeCurrentGroup(i);}};}}Indicators.contextType=PerseusI18nContext;class GradedGroupSet extends React.Component{shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}getPromptJSON(){const activeGroupPromptJSON=this._childGroup.getPromptJSON();return getPromptJSON$h(this.props,activeGroupPromptJSON)}render(){const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.props.gradedGroups.length>1){return jsxRuntimeExports.jsx("div",{className:css(styles$i.container),children:this.props.gradedGroups.map((gradedGroup,i)=>{return jsxRuntimeExports.jsx(GradedGroup,{...this.props,...gradedGroup,inGradedGroupSet:false,linterContext:this.props.linterContext},i)})})}const currentGroup=this.props.gradedGroups[this.state.currentGroup];if(!currentGroup){return jsxRuntimeExports.jsx("span",{children:"No current group..."})}const numGroups=this.props.gradedGroups.length;const handleNextQuestion=this.state.currentGroup<numGroups-1?this.handleNextQuestion:null;return jsxRuntimeExports.jsxs("div",{className:css(styles$i.container),children:[jsxRuntimeExports.jsxs("div",{className:css(styles$i.top),children:[jsxRuntimeExports.jsx("div",{className:css(styles$i.title),children:currentGroup.title}),jsxRuntimeExports.jsx("div",{className:css(styles$i.spacer)}),jsxRuntimeExports.jsx(Indicators,{currentGroup:this.state.currentGroup,gradedGroups:this.props.gradedGroups,onChangeCurrentGroup:currentGroup=>this.setState({currentGroup})})]}),jsxRuntimeExports.jsx(GradedGroup,{ref:comp=>this._childGroup=comp,...this.props,...currentGroup,inGradedGroupSet:true,title:null,onNextQuestion:handleNextQuestion,linterContext:this.props.linterContext},this.state.currentGroup)]})}constructor(...args){super(...args),this.state={currentGroup:0},this.getInputPaths=()=>{return this._childGroup.getInputPaths()},this.focus=()=>{return this._childGroup.focus()},this.focusInputPath=path=>{this._childGroup.focusInputPath(path);},this.blurInputPath=path=>{this._childGroup.blurInputPath(path);},this.handleNextQuestion=()=>{const{currentGroup}=this.state;const numGroups=this.props.gradedGroups.length;if(currentGroup<numGroups-1){this.setState({currentGroup:currentGroup+1});}};}}GradedGroupSet.defaultProps={gradedGroups:[],linterContext:linterContextDefault};var GradedGroupSet$1 = {name:"graded-group-set",displayName:"Graded group set (articles only)",widget:GradedGroupSet,hidden:false,tracking:"all",isLintable:true};const styles$i=StyleSheet.create({top:{display:"flex",flexDirection:"row"},spacer:{flex:1},title:{fontSize:12,color:color.offBlack64,textTransform:"uppercase",marginBottom:11,letterSpacing:.8},indicatorContainer:{display:"flex",flexDirection:"row",listStyle:"none",margin:"unset",paddingInlineStart:"unset",flexWrap:"wrap"},indicator:{width:24,height:24},indicatorButton:{width:"100%",height:"100%",display:"flex",flexWrap:"wrap",placeContent:"center",cursor:"pointer",":focus":{outline:"none"}},indicatorDot:{boxSizing:"content-box",width:10,height:10,borderRadius:"100%",borderWidth:2,borderColor:color.blue,borderStyle:"solid"},indicatorDotFocused:{borderWidth:5,borderStyle:"double"},indicatorDotActive:{backgroundColor:color.blue,width:"100%",height:"100%"},container:{borderTop:`1px solid ${gray76}`,borderBottom:`1px solid ${gray76}`,backgroundColor:tableBackgroundAccent,"--perseus-widget-background-color":tableBackgroundAccent,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"}});
1816
+ class Indicators extends React.Component{render(){return jsxRuntimeExports.jsx("ul",{className:classNames$1(css(styles$i.indicatorContainer),"indicatorContainer"),children:this.props.gradedGroups.map(({title},i)=>jsxRuntimeExports.jsx("li",{className:css(styles$i.indicator),children:jsxRuntimeExports.jsx(Clickable,{role:"button","aria-label":this.context.strings.skipToTitle({title}),style:styles$i.indicatorButton,onClick:()=>this.props.onChangeCurrentGroup(i),onKeyDown:e=>this.handleKeyDown(e,i),children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(View,{style:[styles$i.indicatorDot,(hovered||focused||pressed)&&styles$i.indicatorDotFocused],children:i===this.props.currentGroup&&jsxRuntimeExports.jsx(View,{style:styles$i.indicatorDotActive,children:jsxRuntimeExports.jsx("span",{className:css(a11y.srOnly),children:this.context.strings.current})})})})},title))})}constructor(...args){super(...args),this.handleKeyDown=(e,i)=>{if(e.key==="Enter"||e.key===" "){this.props.onChangeCurrentGroup(i);}};}}Indicators.contextType=PerseusI18nContext;class GradedGroupSet extends React.Component{shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}getPromptJSON(){const activeGroupPromptJSON=this._childGroup.getPromptJSON();return getPromptJSON$h(this.props,activeGroupPromptJSON)}render(){const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.props.gradedGroups.length>1){return jsxRuntimeExports.jsx("div",{className:css(styles$i.container),children:this.props.gradedGroups.map((gradedGroup,i)=>{return jsxRuntimeExports.jsx(GradedGroup,{...this.props,...gradedGroup,inGradedGroupSet:false,linterContext:this.props.linterContext},i)})})}const currentGroup=this.props.gradedGroups[this.state.currentGroup];if(!currentGroup){return jsxRuntimeExports.jsx("span",{children:"No current group..."})}const numGroups=this.props.gradedGroups.length;const handleNextQuestion=this.state.currentGroup<numGroups-1?this.handleNextQuestion:null;return jsxRuntimeExports.jsxs("div",{className:css(styles$i.container),children:[jsxRuntimeExports.jsxs("div",{className:css(styles$i.top),children:[jsxRuntimeExports.jsx("div",{className:css(styles$i.title),children:currentGroup.title}),jsxRuntimeExports.jsx("div",{className:css(styles$i.spacer)}),jsxRuntimeExports.jsx(Indicators,{currentGroup:this.state.currentGroup,gradedGroups:this.props.gradedGroups,onChangeCurrentGroup:currentGroup=>this.setState({currentGroup})})]}),jsxRuntimeExports.jsx(GradedGroup,{ref:comp=>this._childGroup=comp,...this.props,...currentGroup,inGradedGroupSet:true,title:null,onNextQuestion:handleNextQuestion,linterContext:this.props.linterContext},this.state.currentGroup)]})}constructor(...args){super(...args),this.state={currentGroup:0},this.getInputPaths=()=>{return this._childGroup.getInputPaths()},this.focus=()=>{return this._childGroup.focus()},this.focusInputPath=path=>{this._childGroup.focusInputPath(path);},this.blurInputPath=path=>{this._childGroup.blurInputPath(path);},this.handleNextQuestion=()=>{const{currentGroup}=this.state;const numGroups=this.props.gradedGroups.length;if(currentGroup<numGroups-1){this.setState({currentGroup:currentGroup+1});}};}}GradedGroupSet.defaultProps={gradedGroups:[],linterContext:linterContextDefault};var GradedGroupSet$1 = {name:"graded-group-set",displayName:"Graded group set (articles only)",widget:GradedGroupSet,hidden:false,tracking:"all",isLintable:true};const styles$i=StyleSheet.create({top:{display:"flex",flexDirection:"row"},spacer:{flex:1},title:{fontSize:12,color:color.offBlack64,textTransform:"uppercase",marginBottom:11,letterSpacing:.8},indicatorContainer:{display:"flex",flexDirection:"row",listStyle:"none",margin:"unset",paddingInlineStart:"unset",flexWrap:"wrap"},indicator:{width:24,height:24},indicatorButton:{width:"100%",height:"100%",display:"flex",flexWrap:"wrap",placeContent:"center",cursor:"pointer",":focus":{outline:"none"}},indicatorDot:{boxSizing:"content-box",width:10,height:10,borderRadius:"100%",borderWidth:2,borderColor:color.blue,borderStyle:"solid"},indicatorDotFocused:{borderWidth:5,borderStyle:"double"},indicatorDotActive:{backgroundColor:color.blue,width:"100%",height:"100%"},container:{borderTop:`1px solid ${gray76}`,borderBottom:`1px solid ${gray76}`,backgroundColor:tableBackgroundAccent,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"}});
1816
1817
 
1817
1818
  class ButtonGroup extends React.Component{componentWillUnmount(){this.container=null;}focus(){if(this.container){this.container.focus();return true}}toggleSelect(newValue){const value=this.props.value;if(this.props.allowEmpty){this.props.onChange(value!==newValue?newValue:null);}else {this.props.onChange(newValue);}}render(){const value=this.props.value;const buttons=this.props.buttons.map((button,i)=>{return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",ref:"button"+i,className:css(styles$h.buttonStyle,button.value===value&&styles$h.selectedStyle,button.value===value&&this.props.selectedButtonStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:node=>this.container=node,children:buttons})}}ButtonGroup.defaultProps={value:null,allowEmpty:true};const styles$h=StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"}});
1818
1819
 
@@ -1957,13 +1958,13 @@ const TextLabel=({children,...rest})=>jsxRuntimeExports.jsx(Text$2,{size:16,svgT
1957
1958
 
1958
1959
  const{clockwise: clockwise$1}=geometry;const{getAngleFromVertex: getAngleFromVertex$1}=angles;const PolygonAngle=({centerPoint,endPoints,showAngles,snapTo,areEndPointsClockwise})=>{const{range}=useGraphConfig();const[centerX,centerY]=centerPoint;const[[startX,startY],[endX,endY]]=areEndPointsClockwise?endPoints:endPoints.reverse();const radius=calculateScaledRadius(range);const a=vec.dist(centerPoint,endPoints[0]);const b=vec.dist(centerPoint,endPoints[1]);const c=vec.dist(endPoints[0],endPoints[1]);let lawOfCosinesRadicand=(a**2+b**2-c**2)/(2*a*b);if(lawOfCosinesRadicand<-1||lawOfCosinesRadicand>1){lawOfCosinesRadicand=Math.round(lawOfCosinesRadicand);}const angle=Math.acos(lawOfCosinesRadicand);const y1=centerY+(startY-centerY)/a*radius;const x2=centerX+(endX-centerX)/b*radius;const x1=centerX+(startX-centerX)/a*radius;const y2=centerY+(endY-centerY)/b*radius;const[x3,y3]=vec.add(centerPoint,vec.add(vec.sub([x1,y1],centerPoint),vec.sub([x2,y2],centerPoint)));if(!showAngles){return isRightPolygonAngle(angle)?jsxRuntimeExports.jsx(RightAngleSquare,{start:[x1,y1],vertex:[x2,y2],end:[x3,y3],nonScalingStroke:true}):null}const isConcave=isConcavePolygonVertex(centerPoint,endPoints);const largeArcFlag=isConcave?1:0;const arc=`M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`;let angleInDegrees=angle*(180/Math.PI);if(isConcave){angleInDegrees=360-angleInDegrees;}const angleLabelNumber=parseFloat(angleInDegrees.toFixed(snapTo==="angles"?0:1));const angleLabel=Number.isInteger(angleLabelNumber)?angleLabelNumber:"≈ "+angleLabelNumber;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsxs("filter",{id:"background",x:"-5%",width:"110%",y:"0%",height:"100%",children:[jsxRuntimeExports.jsx("feFlood",{floodColor:"#FFF",floodOpacity:"0.5"}),jsxRuntimeExports.jsx("feComposite",{operator:"over",in:"SourceGraphic"})]})}),!isConcave&&isRightPolygonAngle(angle)?jsxRuntimeExports.jsx(RightAngleSquare,{start:[x1,y1],vertex:[x2,y2],end:[x3,y3],nonScalingStroke:true}):jsxRuntimeExports.jsx(Arc,{arc:arc,nonScalingStroke:true}),jsxRuntimeExports.jsxs(TextLabel,{x:x3,y:y3,attach:y3-centerY>0?"s":"n",attachDistance:Math.abs(y3-centerY)<.2||vec.dist([x3,y3],centerPoint)<.3?20:10,children:[angleLabel,"°"]})]})};const Angle=({vertex,coords,showAngles,allowReflexAngles,range})=>{const areClockwise=clockwise$1([...coords,vertex]);const shouldReverseCoords=areClockwise&&!allowReflexAngles;const clockwiseCoords=shouldReverseCoords?coords:coords.reverse();const startAngle=getAngleFromVertex$1(clockwiseCoords[0],vertex);const endAngle=getAngleFromVertex$1(clockwiseCoords[1],vertex);const angle=(startAngle+360-endAngle)%360;const isReflexive=angle>180;const[centerX,centerY]=vertex;const[point1,point2]=clockwiseCoords;const[startX,startY]=point1;const[endX,endY]=point2;const a=vec.dist(vertex,point1);const b=vec.dist(vertex,point2);const radius=2;const y1=centerY+(startY-centerY)/a*radius;const x2=centerX+(endX-centerX)/b*radius;const x1=centerX+(startX-centerX)/a*radius;const y2=centerY+(endY-centerY)/b*radius;const[x3,y3]=vec.add(vertex,vec.add(vec.sub([x1,y1],vertex),vec.sub([x2,y2],vertex)));const isOutside=shouldDrawArcOutside([x3,y3],vertex,range,[[vertex,point1],[vertex,point2]]);const largeArcFlag=isOutside||isReflexive?1:0;const sweepFlag=isOutside&&isReflexive?1:0;const arc=`M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;const angleLabel=parseFloat(angle.toFixed(0));const[textX,textY]=calculateBisectorPoint(point1,point2,vertex,isReflexive,allowReflexAngles,radius);const{disableKeyboardInteraction}=useGraphConfig();const arcClassName=disableKeyboardInteraction?"angle-arc-static":"angle-arc-interactive";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsxs("filter",{id:"background",x:"-5%",width:"110%",y:"0%",height:"100%",children:[jsxRuntimeExports.jsx("feFlood",{floodColor:"#FFF",floodOpacity:"0.5"}),jsxRuntimeExports.jsx("feComposite",{operator:"over",in:"SourceGraphic"})]})}),isRightAngle(angle)?jsxRuntimeExports.jsx(RightAngleSquare,{start:[x1,y1],vertex:[x2,y2],end:[x3,y3],className:arcClassName}):jsxRuntimeExports.jsx(Arc,{arc:arc,className:arcClassName}),showAngles&&jsxRuntimeExports.jsxs(TextLabel,{x:textX,y:textY,color:color.blue,children:[angleLabel,"°"]})]})};const RightAngleSquare=({start:[x1,y1],vertex:[x2,y2],end:[x3,y3],className,nonScalingStroke})=>jsxRuntimeExports.jsx(MafsCssTransformWrapper,{children:jsxRuntimeExports.jsx("path",{"aria-hidden":true,d:`M ${x1} ${y1} L ${x3} ${y3} M ${x3} ${y3} L ${x2} ${y2}`,strokeWidth:1,fill:"none",className:className,"data-testid":"angle-indicators__right-angle",vectorEffect:nonScalingStroke?"non-scaling-stroke":"none"})});const Arc=({arc,className,nonScalingStroke})=>{return jsxRuntimeExports.jsx(MafsCssTransformWrapper,{children:jsxRuntimeExports.jsx("path",{"aria-hidden":true,d:arc,strokeWidth:1,fill:"none",className:className,"data-testid":"angle-indicators__arc",vectorEffect:nonScalingStroke?"non-scaling-stroke":"none"})})};const isRightPolygonAngle=angle=>Math.abs(angle-Math.PI/2)<.01;const isRightAngle=angle=>Math.round(angle)===90;const shouldDrawArcOutside=(midpoint,vertex,range,polygonLines)=>{const rangeIntersectionPoint=getIntersectionOfRayWithBox(midpoint,vertex,range);let lineIntersectionCount=0;polygonLines.forEach(line=>segmentsIntersect([vertex,rangeIntersectionPoint],line)&&lineIntersectionCount++);return !isEven(lineIntersectionCount)};const isEven=n=>n%2===0;function isConcavePolygonVertex(centerPoint,clockwiseEndpoints){const v1=vec.sub(clockwiseEndpoints[1],centerPoint);const v2=vec.sub(clockwiseEndpoints[0],centerPoint);const crossProduct=v1[0]*v2[1]-v1[1]*v2[0];return crossProduct>0}function calculateBisectorPoint(point1,point2,vertex,isReflex,allowReflex,arcRadius){const[originX,originY]=vertex;const[x1,y1]=point1;const[x2,y2]=point2;const vectorA=[x1-originX,y1-originY];const vectorB=[x2-originX,y2-originY];const angleA=Math.atan2(vectorA[1],vectorA[0]);const angleB=Math.atan2(vectorB[1],vectorB[0]);let averageAngle=(angleA+angleB)/2;const angleRadians=Math.abs(angleA-angleB);if(allowReflex){if(angleRadians<=Math.PI&&isReflex||angleB>angleA){averageAngle+=Math.PI;}}else {if(angleRadians>Math.PI){averageAngle-=Math.PI;}}const sum=[Math.cos(averageAngle),Math.sin(averageAngle)];const sumMagnitude=Math.sqrt(sum[0]**2+sum[1]**2);const bisectorDirection=[sum[0]/sumMagnitude,sum[1]/sumMagnitude];const initialDistance=Math.sqrt(bisectorDirection[0]**2+bisectorDirection[1]**2);const requiredDistance=arcRadius*1.75;let radius=requiredDistance/initialDistance;if(initialDistance>=requiredDistance){radius=1;}const bisectorPoint=[bisectorDirection[0]*radius,bisectorDirection[1]*radius];const scaledBisector=vec.add(bisectorPoint,vertex);return scaledBisector}
1959
1960
 
1960
- function useDraggable(args){const{gestureTarget:target,onMove,point,constrainKeyboardMovement}=args;const[dragging,setDragging]=React.useState(false);const{xSpan,ySpan}=useSpanContext();const{viewTransform,userTransform}=useTransformContext();const inverseViewTransform=vec.matrixInvert(viewTransform);invariant(inverseViewTransform,"The view transform must be invertible.");const inverseTransform=React.useMemo(()=>getInverseTransform(userTransform),[userTransform]);const pickup=React.useRef([0,0]);useDrag(state=>{const{type,event}=state;event?.stopPropagation();const isKeyboard=type.includes("key");if(isKeyboard){invariant(event instanceof KeyboardEvent);event?.preventDefault();if(type==="keyup"){return}if(typeof constrainKeyboardMovement==="object"){const destination=constrainKeyboardMovement[directionForKey[event.key]];onMove(destination??point);return}const{direction:yDownDirection,altKey,ctrlKey,metaKey,shiftKey}=state;const direction=[yDownDirection[X],-yDownDirection[Y]];const span=Math.abs(direction[X])?xSpan:ySpan;let divisions=50;if(altKey||metaKey){divisions=200;}if(shiftKey&&!ctrlKey){divisions=10;}const min=span/(divisions*2);const tests=range(span/divisions,span/2,span/divisions);for(const dx of tests){const testMovement=vec.scale(direction,dx);const testPoint=constrainKeyboardMovement(vec.transform(vec.add(vec.transform(point,userTransform),testMovement),inverseTransform));if(vec.dist(testPoint,point)>min){onMove(testPoint);break}}}else {const{last,movement:pixelMovement,first}=state;setDragging(!last);if(first){pickup.current=vec.transform(point,userTransform);}if(vec.mag(pixelMovement)===0){return}const movement=vec.transform(pixelMovement,inverseViewTransform);onMove(vec.transform(vec.add(pickup.current,movement),inverseTransform));}},{target,eventOptions:{passive:false}});return {dragging}}const directionForKey={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down"};function getInverseTransform(transform){const invert=vec.matrixInvert(transform);invariant(invert!==null,"Could not invert transform matrix. A parent transformation matrix might be degenerative (mapping 2D space to a line).");return invert}function useSpanContext(){const{range:[[xMin,xMax],[yMin,yMax]]}=useGraphConfig();const xSpan=xMax-xMin;const ySpan=yMax-yMin;return {xSpan,ySpan}}function range(min,max,step=1){const result=[];for(let i=min;i<max-step/2;i+=step){result.push(i);}const computedMax=result[result.length-1]+step;if(Math.abs(max-computedMax)<step/1e-6){result.push(max);}else {result.push(computedMax);}return result}
1961
+ function useDraggable(args){const{gestureTarget:target,onMove,onDragEnd,point,constrainKeyboardMovement}=args;const[dragging,setDragging]=React.useState(false);const{xSpan,ySpan}=useSpanContext();const{viewTransform,userTransform}=useTransformContext();const inverseViewTransform=vec.matrixInvert(viewTransform);invariant(inverseViewTransform,"The view transform must be invertible.");const inverseTransform=React.useMemo(()=>getInverseTransform(userTransform),[userTransform]);const pickup=React.useRef([0,0]);useDrag(state=>{const{type,event}=state;event?.stopPropagation();const isKeyboard=type.includes("key");if(isKeyboard){invariant(event instanceof KeyboardEvent);event?.preventDefault();if(type==="keyup"){return}if(typeof constrainKeyboardMovement==="object"){const destination=constrainKeyboardMovement[directionForKey[event.key]];onMove(destination??point);return}const{direction:yDownDirection,altKey,ctrlKey,metaKey,shiftKey}=state;const direction=[yDownDirection[X],-yDownDirection[Y]];const span=Math.abs(direction[X])?xSpan:ySpan;let divisions=50;if(altKey||metaKey){divisions=200;}if(shiftKey&&!ctrlKey){divisions=10;}const min=span/(divisions*2);const tests=range(span/divisions,span/2,span/divisions);for(const dx of tests){const testMovement=vec.scale(direction,dx);const testPoint=constrainKeyboardMovement(vec.transform(vec.add(vec.transform(point,userTransform),testMovement),inverseTransform));if(vec.dist(testPoint,point)>min){onMove(testPoint);break}}}else {const{last,movement:pixelMovement,first}=state;setDragging(!last);if(last&&onDragEnd){onDragEnd();}if(first){pickup.current=vec.transform(point,userTransform);}if(vec.mag(pixelMovement)===0){return}const movement=vec.transform(pixelMovement,inverseViewTransform);onMove(vec.transform(vec.add(pickup.current,movement),inverseTransform));}},{target,eventOptions:{passive:false}});return {dragging}}const directionForKey={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down"};function getInverseTransform(transform){const invert=vec.matrixInvert(transform);invariant(invert!==null,"Could not invert transform matrix. A parent transformation matrix might be degenerative (mapping 2D space to a line).");return invert}function useSpanContext(){const{range:[[xMin,xMax],[yMin,yMax]]}=useGraphConfig();const xSpan=xMax-xMin;const ySpan=yMax-yMin;return {xSpan,ySpan}}function range(min,max,step=1){const result=[];for(let i=min;i<max-step/2;i+=step){result.push(i);}const computedMax=result[result.length-1]+step;if(Math.abs(max-computedMax)<step/1e-6){result.push(max);}else {result.push(computedMax);}return result}
1961
1962
 
1962
1963
  function Hairlines(props){const{point}=props;const{range}=useGraphConfig();const[[xMin,xMax],[yMin,yMax]]=range;const[[x,y]]=useTransformVectorsToPixels(point);const[[verticalStartX]]=useTransformVectorsToPixels([xMin,0]);const[[verticalEndX]]=useTransformVectorsToPixels([xMax,0]);const[[_,horizontalStartY]]=useTransformVectorsToPixels([0,yMin]);const[[__,horizontalEndY]]=useTransformVectorsToPixels([0,yMax]);return jsxRuntimeExports.jsxs("g",{"aria-hidden":true,children:[jsxRuntimeExports.jsx("line",{x1:verticalStartX,y1:y,x2:verticalEndX,y2:y,stroke:color.blue}),jsxRuntimeExports.jsx("line",{x1:x,y1:horizontalStartY,x2:x,y2:horizontalEndY,stroke:color.blue})]})}
1963
1964
 
1964
1965
  const hitboxSizePx=48;const MovablePointView=forwardRef(function MovablePointViewWithRef(props,hitboxRef){const{markings,showTooltips,interactiveColor,disableKeyboardInteraction,snapStep}=useGraphConfig();const{point,dragging,focused,cursor,showFocusRing,onClick=()=>{}}=props;const wbColorName=disableKeyboardInteraction?"fadedOffBlack64":"blue";const pointClasses=classNames("movable-point",dragging&&"movable-point--dragging",showFocusRing&&"movable-point--focus");const[[x,y]]=useTransformVectorsToPixels(point);const showHairlines=(dragging||focused)&&markings!=="none";const xSigFigs=countSignificantDecimals(snapStep[X]);const ySigFigs=countSignificantDecimals(snapStep[Y]);const xTickLabel=point[X].toFixed(xSigFigs);const yTickLabel=point[Y].toFixed(ySigFigs);const pointTooltipContent=`(${xTickLabel}, ${yTickLabel})`;const svgForPoint=jsxRuntimeExports.jsxs("g",{"aria-hidden":true,ref:hitboxRef,className:pointClasses,style:{"--movable-point-color":interactiveColor,cursor},"data-testid":"movable-point",onClick:onClick,children:[jsxRuntimeExports.jsx("circle",{className:"movable-point-hitbox",r:hitboxSizePx/2,cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-halo",cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-ring",cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-focus-outline",cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-center",cx:x,cy:y,style:{fill:interactiveColor},"data-testid":"movable-point__center"})]});return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[showHairlines&&jsxRuntimeExports.jsx(Hairlines,{point:point}),showTooltips?jsxRuntimeExports.jsx(Tooltip,{autoUpdate:true,opened:true,backgroundColor:wbColorName,content:pointTooltipContent,contentStyle:{color:"white"},children:svgForPoint}):svgForPoint]})});function classNames(...names){return names.filter(Boolean).join(" ")}
1965
1966
 
1966
- function useControlPoint(params){const{snapStep,disableKeyboardInteraction}=useGraphConfig();const{point,ariaDescribedBy,ariaLabel,ariaLive="polite",constrain=p=>snap(snapStep,p),cursor,forwardedRef=noop,sequenceNumber=1,onMove=noop,onClick=noop,onFocus=noop,onBlur=noop}=params;const{strings,locale}=usePerseusI18n();const[focused,setFocused]=useState(false);const focusableHandleRef=useRef(null);useDraggable({gestureTarget:focusableHandleRef,point,onMove,constrainKeyboardMovement:constrain});const visiblePointRef=useRef(null);const{dragging}=useDraggable({gestureTarget:visiblePointRef,point,onMove,constrainKeyboardMovement:constrain});const pointAriaLabel=ariaLabel||strings.srPointAtCoordinates({num:sequenceNumber,x:srFormatNumber(point[X],locale),y:srFormatNumber(point[Y],locale)});useLayoutEffect(()=>{setForwardedRef(forwardedRef,focusableHandleRef.current);},[forwardedRef]);useLayoutEffect(()=>{if(dragging&&!focused){focusableHandleRef.current?.focus();}},[dragging,focused]);const focusableHandle=jsxRuntimeExports.jsx("g",{"data-testid":"movable-point__focusable-handle",className:"movable-point__focusable-handle",tabIndex:disableKeyboardInteraction?-1:0,ref:focusableHandleRef,role:"button","aria-describedby":ariaDescribedBy,"aria-label":pointAriaLabel,"aria-live":ariaLive,"aria-disabled":disableKeyboardInteraction,onFocus:event=>{onFocus(event);setFocused(true);},onBlur:event=>{onBlur(event);setFocused(false);}});const visiblePoint=jsxRuntimeExports.jsx(MovablePointView,{cursor:cursor,onClick:()=>{onClick();focusableHandleRef.current?.focus();},point:point,dragging:dragging,focused:focused,ref:visiblePointRef,showFocusRing:focused});return {focusableHandle,visiblePoint,focusableHandleRef,visiblePointRef}}function setForwardedRef(ref,value){if(typeof ref==="function"){ref(value);}else if(ref!==null){ref.current=value;}}const noop=()=>{};
1967
+ function useControlPoint(params){const{snapStep,disableKeyboardInteraction}=useGraphConfig();const{point,ariaDescribedBy,ariaLabel,ariaLive="polite",constrain=p=>snap(snapStep,p),cursor,forwardedRef=noop,sequenceNumber=1,onMove=noop,onDragEnd=noop,onClick=noop,onFocus=noop,onBlur=noop}=params;const{strings,locale}=usePerseusI18n();const[focused,setFocused]=useState(false);const focusableHandleRef=useRef(null);useDraggable({gestureTarget:focusableHandleRef,point,onMove,onDragEnd,constrainKeyboardMovement:constrain});const visiblePointRef=useRef(null);const{dragging}=useDraggable({gestureTarget:visiblePointRef,point,onMove,onDragEnd,constrainKeyboardMovement:constrain});const pointAriaLabel=ariaLabel||strings.srPointAtCoordinates({num:sequenceNumber,x:srFormatNumber(point[X],locale),y:srFormatNumber(point[Y],locale)});useLayoutEffect(()=>{setForwardedRef(forwardedRef,focusableHandleRef.current);},[forwardedRef]);useLayoutEffect(()=>{if(dragging&&!focused){focusableHandleRef.current?.focus();}},[dragging,focused]);const focusableHandle=jsxRuntimeExports.jsx("g",{"data-testid":"movable-point__focusable-handle",className:"movable-point__focusable-handle",tabIndex:disableKeyboardInteraction?-1:0,ref:focusableHandleRef,role:"button","aria-describedby":ariaDescribedBy,"aria-label":pointAriaLabel,"aria-live":ariaLive,"aria-disabled":disableKeyboardInteraction,onFocus:event=>{onFocus(event);setFocused(true);},onBlur:event=>{onBlur(event);setFocused(false);}});const visiblePoint=jsxRuntimeExports.jsx(MovablePointView,{cursor:cursor,onClick:()=>{onClick();focusableHandleRef.current?.focus();},point:point,dragging:dragging,focused:focused,ref:visiblePointRef,showFocusRing:focused});return {focusableHandle,visiblePoint,focusableHandleRef,visiblePointRef}}function setForwardedRef(ref,value){if(typeof ref==="function"){ref(value);}else if(ref!==null){ref.current=value;}}const noop=()=>{};
1967
1968
 
1968
1969
  const MovableLine=props=>{const{points:[start,end],ariaLabels,ariaDescribedBy,extend,onMoveLine=()=>{},onMovePoint=()=>{}}=props;const{snapStep}=useGraphConfig();const[ariaLives,setAriaLives]=React.useState(["off","off","off"]);const{visiblePoint:visiblePoint1,focusableHandle:focusableHandle1}=useControlPoint({ariaLabel:ariaLabels?.point1AriaLabel,ariaDescribedBy:ariaDescribedBy,ariaLive:ariaLives[0],point:start,sequenceNumber:1,onMove:p=>{setAriaLives(["polite","off","off"]);onMovePoint(0,p);},constrain:getMovableLineKeyboardConstraint([start,end],snapStep,0)});const{visiblePoint:visiblePoint2,focusableHandle:focusableHandle2}=useControlPoint({ariaLabel:ariaLabels?.point2AriaLabel,ariaDescribedBy:ariaDescribedBy,ariaLive:ariaLives[1],point:end,sequenceNumber:2,onMove:p=>{setAriaLives(["off","polite","off"]);onMovePoint(1,p);},constrain:getMovableLineKeyboardConstraint([start,end],snapStep,1)});const line=jsxRuntimeExports.jsx(Line$1,{ariaLabel:ariaLabels?.grabHandleAriaLabel,ariaDescribedBy:ariaDescribedBy,ariaLive:ariaLives[2],start:start,end:end,extend:extend,onMove:delta=>{setAriaLives(["off","off","polite"]);onMoveLine(delta);}});return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[focusableHandle1,line,focusableHandle2,visiblePoint1,visiblePoint2]})};const Line$1=props=>{const{start,end,ariaLabel,ariaDescribedBy,ariaLive,extend,onMove}=props;const[startPtPx,endPtPx]=useTransformVectorsToPixels(start,end);const{range,graphDimensionsInPixels,snapStep,disableKeyboardInteraction,interactiveColor}=useGraphConfig();let startExtend=undefined;let endExtend=undefined;if(extend){const trimmedRange=trimRange(range,graphDimensionsInPixels);startExtend=extend.start?getIntersectionOfRayWithBox(end,start,trimmedRange):undefined;endExtend=extend.end?getIntersectionOfRayWithBox(start,end,trimmedRange):undefined;}const line=useRef(null);const{dragging}=useDraggable({gestureTarget:line,point:start,onMove:newPoint=>{onMove(vec.sub(newPoint,start));},constrainKeyboardMovement:p=>snap(snapStep,p)});return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("g",{ref:line,tabIndex:disableKeyboardInteraction?-1:0,"aria-label":ariaLabel,"aria-describedby":ariaDescribedBy,"aria-live":ariaLive,"aria-disabled":disableKeyboardInteraction,className:"movable-line","data-testid":"movable-line",style:{cursor:dragging?"grabbing":"grab"},role:"button",children:[jsxRuntimeExports.jsx(SVGLine,{start:startPtPx,end:endPtPx,style:{stroke:"transparent",strokeWidth:TARGET_SIZE}}),jsxRuntimeExports.jsx(SVGLine,{start:startPtPx,end:endPtPx,className:"movable-line-focus-outline",style:{}}),jsxRuntimeExports.jsx(SVGLine,{start:startPtPx,end:endPtPx,className:"movable-line-focus-outline-gap",style:{}}),jsxRuntimeExports.jsx(SVGLine,{start:startPtPx,end:endPtPx,style:{stroke:interactiveColor,strokeWidth:"var(--movable-line-stroke-weight)"},className:dragging?"movable-dragging":"",testId:"movable-line__line"})]}),startExtend&&jsxRuntimeExports.jsx(Vector,{tail:start,tip:startExtend,testId:"movable-line__vector"}),endExtend&&jsxRuntimeExports.jsx(Vector,{tail:end,tip:endExtend,testId:"movable-line__vector"})]})};const getMovableLineKeyboardConstraint=(line,snapStep,pointIndex)=>{const coordToBeMoved=line[pointIndex];const otherPoint=line[1-pointIndex];const movePointWithConstraint=moveFunc=>{let movedCoord=moveFunc(coordToBeMoved);if(vec.dist(movedCoord,otherPoint)===0){movedCoord=moveFunc(movedCoord);}return movedCoord};return {up:movePointWithConstraint(coord=>vec.add(coord,[0,snapStep[1]])),down:movePointWithConstraint(coord=>vec.sub(coord,[0,snapStep[1]])),left:movePointWithConstraint(coord=>vec.sub(coord,[snapStep[0],0])),right:movePointWithConstraint(coord=>vec.add(coord,[snapStep[0],0]))}};function trimRange(range,graphDimensionsInPixels){const pixelsToTrim=4;const[xRange,yRange]=range;const[pixelsWide,pixelsTall]=graphDimensionsInPixels;const graphUnitsPerPixelX=size(xRange)/pixelsWide;const graphUnitsPerPixelY=size(yRange)/pixelsTall;const graphUnitsToTrimX=pixelsToTrim*graphUnitsPerPixelX;const graphUnitsToTrimY=pixelsToTrim*graphUnitsPerPixelY;return inset([graphUnitsToTrimX,graphUnitsToTrimY],range)}
1969
1970
 
@@ -1981,13 +1982,13 @@ function renderLinearGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.
1981
1982
 
1982
1983
  function renderLinearSystemGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.jsx(LinearSystemGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getLinearSystemGraphDescription(state,i18n)}}const LinearSystemGraph=props=>{const{dispatch}=props;const{coords:lines}=props.graphState;const{strings,locale}=usePerseusI18n();const id=React.useId();const intersectionId=`${id}-intersection`;const intersectionPoint=geometry.getLineIntersection(lines[0],lines[1]);const intersectionDescription=intersectionPoint?strings.srLinearSystemIntersection({x:srFormatNumber(intersectionPoint[0],locale),y:srFormatNumber(intersectionPoint[1],locale)}):strings.srLinearSystemParallel;const linesAriaInfo=lines.map((line,i)=>{return {pointsDescriptionId:`${id}-line${i+1}-points`,interceptDescriptionId:`${id}-line${i+1}-intercept`,slopeDescriptionId:`${id}-line${i+1}-slope`,pointsDescription:strings.srLinearSystemPoints({lineNumber:i+1,point1X:srFormatNumber(line[0][0],locale),point1Y:srFormatNumber(line[0][1],locale),point2X:srFormatNumber(line[1][0],locale),point2Y:srFormatNumber(line[1][1],locale)}),interceptDescription:getInterceptStringForLine(line,strings,locale),slopeDescription:getSlopeStringForLine(line,strings)}});const individualLineDescriptions=linesAriaInfo.map(({pointsDescriptionId,interceptDescriptionId,slopeDescriptionId})=>`${pointsDescriptionId} ${interceptDescriptionId} ${slopeDescriptionId}`).join(" ");return jsxRuntimeExports.jsxs("g",{"aria-label":strings.srLinearSystemGraph,"aria-describedby":`${individualLineDescriptions} ${intersectionId}`,children:[lines?.map((line,i)=>jsxRuntimeExports.jsx(MovableLine,{points:line,ariaLabels:{point1AriaLabel:strings.srLinearSystemPoint({lineNumber:i+1,pointSequence:1,x:srFormatNumber(line[0][0],locale),y:srFormatNumber(line[0][1],locale)}),point2AriaLabel:strings.srLinearSystemPoint({lineNumber:i+1,pointSequence:2,x:srFormatNumber(line[1][0],locale),y:srFormatNumber(line[1][1],locale)}),grabHandleAriaLabel:strings.srLinearSystemGrabHandle({lineNumber:i+1,point1X:srFormatNumber(line[0][0],locale),point1Y:srFormatNumber(line[0][1],locale),point2X:srFormatNumber(line[1][0],locale),point2Y:srFormatNumber(line[1][1],locale)})},ariaDescribedBy:`${linesAriaInfo[i].interceptDescriptionId} ${linesAriaInfo[i].slopeDescriptionId} ${intersectionId}`,onMoveLine:delta=>{dispatch(actions.linearSystem.moveLine(i,delta));},extend:{start:true,end:true},onMovePoint:(endpointIndex,destination)=>dispatch(actions.linearSystem.movePointInFigure(i,endpointIndex,destination))},i)),linesAriaInfo.map(({pointsDescriptionId,interceptDescriptionId,slopeDescriptionId,pointsDescription,interceptDescription,slopeDescription},i)=>jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsx(SRDescInSVG,{id:pointsDescriptionId,children:pointsDescription}),jsxRuntimeExports.jsx(SRDescInSVG,{id:interceptDescriptionId,children:interceptDescription}),jsxRuntimeExports.jsx(SRDescInSVG,{id:slopeDescriptionId,children:slopeDescription})]},`line-descriptions-${i}`)),jsxRuntimeExports.jsx(SRDescInSVG,{id:intersectionId,children:intersectionDescription})]})};function getLinearSystemGraphDescription(state,i18n){const{strings,locale}=i18n;const{coords:lines}=state;const graphDescription=strings.srLinearSystemGraph;const lineDescriptions=lines.map((line,i)=>{const point1=line[0];const point2=line[1];return strings.srLinearSystemPoints({lineNumber:i+1,point1X:srFormatNumber(point1[0],locale),point1Y:srFormatNumber(point1[1],locale),point2X:srFormatNumber(point2[0],locale),point2Y:srFormatNumber(point2[1],locale)})});const allDescriptions=[graphDescription,...lineDescriptions];return strings.srInteractiveElements({elements:allDescriptions.join(" ")})}
1983
1984
 
1984
- function renderPointGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.jsx(PointGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getPointGraphDescription(state,i18n)}}function PointGraph(props){const{numPoints}=props.graphState;const graphConfig=useGraphConfig();const pointsRef=React.useRef([]);const{range:[x,y]}=graphConfig;const[[left,top]]=useTransformVectorsToPixels([x[0],y[1]]);React.useEffect(()=>{const focusedIndex=props.graphState.focusedPointIndex;if(focusedIndex!=null){pointsRef.current[focusedIndex]?.focus();}},[props.graphState.focusedPointIndex,props.graphState.coords.length,pointsRef]);const statefulProps={...props,graphConfig,pointsRef,top,left};if(numPoints==="unlimited"){return UnlimitedPointGraph(statefulProps)}return LimitedPointGraph(statefulProps)}function LimitedPointGraph(statefulProps){const{dispatch}=statefulProps;return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:statefulProps.graphState.coords.map((point,i)=>jsxRuntimeExports.jsx(MovablePoint$1,{point:point,sequenceNumber:i+1,onMove:destination=>dispatch(actions.pointGraph.movePoint(i,destination))},i))})}function UnlimitedPointGraph(statefulProps){const{dispatch,graphConfig,pointsRef,top,left}=statefulProps;const{coords}=statefulProps.graphState;const{graphDimensionsInPixels}=graphConfig;const widthPx=graphDimensionsInPixels[0];const heightPx=graphDimensionsInPixels[1];return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("rect",{style:{fill:"rgba(0,0,0,0)",cursor:"crosshair"},width:widthPx,height:heightPx,x:left,y:top,onClick:event=>{const elementRect=event.currentTarget.getBoundingClientRect();const x=event.clientX-elementRect.x;const y=event.clientY-elementRect.y;const graphCoordinates=pixelsToVectors([[x,y]],graphConfig);dispatch(actions.pointGraph.addPoint(graphCoordinates[0]));}}),coords.map((point,i)=>jsxRuntimeExports.jsx(MovablePoint$1,{point:point,sequenceNumber:i+1,onMove:destination=>dispatch(actions.pointGraph.movePoint(i,destination)),ref:ref=>{pointsRef.current[i]=ref;},onFocus:()=>{dispatch(actions.pointGraph.focusPoint(i));},onClick:()=>{dispatch(actions.pointGraph.clickPoint(i));}},i))]})}function getPointGraphDescription(state,i18n){const{strings,locale}=i18n;if(state.coords.length===0){return strings.srNoInteractiveElements}const pointDescriptions=state.coords.map(([x,y],index)=>strings.srPointAtCoordinates({num:index+1,x:srFormatNumber(x,locale),y:srFormatNumber(y,locale)}));return strings.srInteractiveElements({elements:pointDescriptions.join(" ")})}
1985
+ function renderPointGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.jsx(PointGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getPointGraphDescription(state,i18n)}}function PointGraph(props){const{numPoints}=props.graphState;const graphConfig=useGraphConfig();const pointsRef=React.useRef([]);const{range:[x,y]}=graphConfig;const[[left,top]]=useTransformVectorsToPixels([x[0],y[1]]);React.useEffect(()=>{const focusedIndex=props.graphState.focusedPointIndex;if(focusedIndex!=null){pointsRef.current[focusedIndex]?.focus();}},[props.graphState.focusedPointIndex,props.graphState.coords.length,pointsRef]);const statefulProps={...props,graphConfig,pointsRef,top,left};if(numPoints==="unlimited"){return UnlimitedPointGraph(statefulProps)}return LimitedPointGraph(statefulProps)}function LimitedPointGraph(statefulProps){const{dispatch}=statefulProps;return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:statefulProps.graphState.coords.map((point,i)=>jsxRuntimeExports.jsx(MovablePoint$1,{point:point,sequenceNumber:i+1,onMove:destination=>dispatch(actions.pointGraph.movePoint(i,destination))},i))})}function UnlimitedPointGraph(statefulProps){const{dispatch,graphConfig,pointsRef,top,left}=statefulProps;const{coords}=statefulProps.graphState;const[isCurrentlyDragging,setIsCurrentlyDragging]=React.useState(false);const dragEndCallbackTimer=useTimeout(()=>setIsCurrentlyDragging(false),400);const{graphDimensionsInPixels}=graphConfig;const widthPx=graphDimensionsInPixels[0];const heightPx=graphDimensionsInPixels[1];return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("rect",{style:{fill:"rgba(0,0,0,0)",cursor:"crosshair"},width:widthPx,height:heightPx,x:left,y:top,onClick:event=>{if(isCurrentlyDragging){return}const elementRect=event.currentTarget.getBoundingClientRect();const x=event.clientX-elementRect.x;const y=event.clientY-elementRect.y;const graphCoordinates=pixelsToVectors([[x,y]],graphConfig);dispatch(actions.pointGraph.addPoint(graphCoordinates[0]));}}),coords.map((point,i)=>jsxRuntimeExports.jsx(MovablePoint$1,{point:point,sequenceNumber:i+1,onMove:destination=>{setIsCurrentlyDragging(true);dispatch(actions.pointGraph.movePoint(i,destination));},onDragEnd:()=>{dragEndCallbackTimer.set();},ref:ref=>{pointsRef.current[i]=ref;},onFocus:()=>{dispatch(actions.pointGraph.focusPoint(i));},onClick:()=>{dispatch(actions.pointGraph.clickPoint(i));}},i))]})}function getPointGraphDescription(state,i18n){const{strings,locale}=i18n;if(state.coords.length===0){return strings.srNoInteractiveElements}const pointDescriptions=state.coords.map(([x,y],index)=>strings.srPointAtCoordinates({num:index+1,x:srFormatNumber(x,locale),y:srFormatNumber(y,locale)}));return strings.srInteractiveElements({elements:pointDescriptions.join(" ")})}
1985
1986
 
1986
1987
  const{magnitude: magnitude$2,vector: vector$2}=geometry;function initializeGraphState(params){const{graph,step,snapStep,range}=params;const shared={hasBeenInteractedWith:false,range,snapStep};switch(graph.type){case "segment":return {...shared,type:"segment",coords:getSegmentCoords(graph,range,step)};case "linear":return {...shared,type:graph.type,coords:getLineCoords(graph,range,step)};case "ray":return {...shared,type:graph.type,coords:getLineCoords(graph,range,step)};case "linear-system":return {...shared,type:graph.type,coords:getLinearSystemCoords(graph,range,step)};case "polygon":return {...shared,type:"polygon",numSides:graph.numSides||0,showAngles:Boolean(graph.showAngles),showSides:Boolean(graph.showSides),coords:getPolygonCoords(graph,range,step),snapTo:graph.snapTo??"grid",focusedPointIndex:null,showRemovePointButton:false,interactionMode:"mouse",showKeyboardInteractionInvitation:false,closedPolygon:false};case "point":return {...shared,type:graph.type,coords:getPointCoords(graph,range,step),numPoints:graph.numPoints||0,focusedPointIndex:null,showRemovePointButton:false,interactionMode:"mouse",showKeyboardInteractionInvitation:false};case "circle":return {...shared,type:graph.type,...getCircleCoords(graph)};case "quadratic":return {...shared,type:graph.type,coords:getQuadraticCoords(graph,range,step)};case "sinusoid":return {...shared,type:graph.type,coords:getSinusoidCoords(graph,range,step)};case "angle":return {...shared,type:graph.type,showAngles:Boolean(graph.showAngles),coords:getAngleCoords({graph,range,step}),angleOffsetDeg:Number(graph.angleOffsetDeg),allowReflexAngles:Boolean(graph.allowReflexAngles),snapDegrees:Number(graph.snapDegrees)};case "none":return {...shared,type:"none"};default:throw new UnreachableCaseError(graph)}}function getPointCoords(graph,range,step){const numPoints=graph.numPoints||1;let coords=graph.coords?.slice();if(coords){return coords}const startCoords=graph.startCoords?.slice();if(startCoords){return startCoords}switch(numPoints){case 1:coords=[graph.coord||[0,0]];break;case 2:coords=[[-5,0],[5,0]];break;case 3:coords=[[-5,0],[0,0],[5,0]];break;case 4:coords=[[-6,0],[-2,0],[2,0],[6,0]];break;case 5:coords=[[-6,0],[-3,0],[0,0],[3,0],[6,0]];break;case 6:coords=[[-5,0],[-3,0],[-1,0],[1,0],[3,0],[5,0]];break;default:coords=[];break}const newCoords=normalizeCoords(coords,[[-10,10],[-10,10]]);return normalizePoints(range,step,newCoords)}function getSegmentCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const ys=n=>{switch(n){case 2:return [5,-5];case 3:return [5,0,-5];case 4:return [6,2,-2,-6];case 5:return [6,3,0,-3,-6];case 6:return [5,3,1,-1,-3,-5];default:return [5]}};const defaultRange=[[-10,10],[-10,10]];return ys(graph.numSegments).map(y=>{let endpoints=[[-5,y],[5,y]];endpoints=normalizeCoords(endpoints,defaultRange);endpoints=normalizePoints(range,step,endpoints);return endpoints})}const defaultLinearCoords=[[[.25,.75],[.75,.75]],[[.25,.25],[.75,.25]]];function getLineCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}return normalizePoints(range,step,defaultLinearCoords[0])}function getLinearSystemCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}return defaultLinearCoords.map(points=>normalizePoints(range,step,points))}function getPolygonCoords(graph,range,step){let coords=graph.coords?.slice();if(coords){return coords}const startCoords=graph.startCoords?.slice();if(startCoords){return startCoords}const n=graph.numSides||3;if(n==="unlimited"){coords=[];}else {const angle=2*Math.PI/n;const offset=(1/n-1/2)*Math.PI;const radius=graph.snapTo==="sides"?Math.sqrt(3)/3*7:4;coords=[...Array(n).keys()].map(i=>[radius*Math.cos(i*angle+offset),radius*Math.sin(i*angle+offset)]);}coords=normalizeCoords(coords,[[-10,10],[-10,10]]);const snapToGrid=!["angles","sides"].includes(graph.snapTo||"");coords=normalizePoints(range,step,coords,!snapToGrid);return coords}function getSinusoidCoords(graph,range,step){if(graph.coords){return [graph.coords[0],graph.coords[1]]}if(graph.startCoords){return [graph.startCoords[0],graph.startCoords[1]]}let coords=[[.5,.5],[.65,.6]];coords=normalizePoints(range,step,coords,true);return coords}function getQuadraticCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const defaultCoords=[[.25,.75],[.5,.25],[.75,.75]];return normalizePoints(range,step,defaultCoords,true)}function getCircleCoords(graph){if(graph.center!=null&&graph.radius!=null){return {center:graph.center,radiusPoint:vec.add(graph.center,[graph.radius,0])}}if(graph.startCoords?.center&&graph.startCoords.radius){return {center:graph.startCoords.center,radiusPoint:vec.add(graph.startCoords.center,[graph.startCoords.radius,0])}}return {center:[0,0],radiusPoint:[2,0]}}const getAngleCoords=params=>{const{graph,range,step}=params;if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const{snapDegrees,angleOffsetDeg}=graph;const snap=snapDegrees||1;let angle=snap;while(angle<20){angle+=snap;}angle=angle*Math.PI/180;const offset=(angleOffsetDeg||0)*Math.PI/180;let defaultCoords=[[.85,.5],[.5,.5]];defaultCoords=normalizePoints(range,step,defaultCoords,true);const radius=magnitude$2(vector$2(...defaultCoords));const coords=[...defaultCoords,[0,0]];coords[0]=[coords[1][0]+radius*Math.cos(offset),coords[1][1]+radius*Math.sin(offset)];coords[2]=[coords[1][0]+radius*Math.cos(angle+offset),coords[1][1]+radius*Math.sin(angle+offset)];return coords};
1987
1988
 
1988
1989
  const{getAngleFromVertex,getClockwiseAngle: getClockwiseAngle$1,polar}=angles;const{angleMeasures,ccw,lawOfCosines,magnitude: magnitude$1,polygonSidesIntersect,reverseVector,sign,vector: vector$1}=geometry;const{getQuadraticCoefficients: getQuadraticCoefficients$2}=coefficients;const minDistanceBetweenAngleVertexAndSidePoint=2;function interactiveGraphReducer(state,action){switch(action.type){case REINITIALIZE:return initializeGraphState(action.params);case MOVE_POINT_IN_FIGURE:return doMovePointInFigure(state,action);case MOVE_LINE:return doMoveLine(state,action);case MOVE_ALL:return doMoveAll(state,action);case MOVE_POINT:return doMovePoint(state,action);case MOVE_CENTER:return doMoveCenter(state,action);case MOVE_RADIUS_POINT:return doMoveRadiusPoint(state,action);case CHANGE_SNAP_STEP:return doChangeSnapStep(state,action);case CHANGE_RANGE:return doChangeRange(state,action);case ADD_POINT:return doAddPoint(state,action);case REMOVE_POINT:return doRemovePoint(state,action);case FOCUS_POINT:return doFocusPoint(state,action);case BLUR_POINT:return doBlurPoint(state);case DELETE_INTENT:return doDeleteIntent(state);case CLICK_POINT:return doClickPoint(state,action);case CLOSE_POLYGON:return doClosePolygon(state);case OPEN_POLYGON:return doOpenPolygon(state);case CHANGE_INTERACTION_MODE:return doChangeInteractionMode(state,action);case CHANGE_KEYBOARD_INVITATION_VISIBILITY:return doChangeKeyboardInvitationVisibility(state,action);default:throw new UnreachableCaseError(action)}}function doDeleteIntent(state,action){if(isUnlimitedGraphState(state)){if(state.focusedPointIndex!==null){return doRemovePoint(state,actions.pointGraph.removePoint(state.focusedPointIndex))}}return state}function doFocusPoint(state,action){switch(state.type){case "polygon":case "point":return {...state,focusedPointIndex:action.index};default:return state}}function doBlurPoint(state,action){switch(state.type){case "polygon":case "point":const nextState={...state,showRemovePointButton:false};if(state.interactionMode==="mouse"){nextState.focusedPointIndex=null;}return nextState;default:return state}}function doClickPoint(state,action){if(isUnlimitedGraphState(state)){return {...state,focusedPointIndex:action.index,showRemovePointButton:true}}return state}function doClosePolygon(state){if(isUnlimitedGraphState(state)&&state.type==="polygon"){const noDupedPoints=getArrayWithoutDuplicates(state.coords);return {...state,coords:noDupedPoints,closedPolygon:true}}return state}function doOpenPolygon(state){if(isUnlimitedGraphState(state)&&state.type==="polygon"){return {...state,closedPolygon:false}}return state}function doChangeInteractionMode(state,action){if(isUnlimitedGraphState(state)){const nextKeyboardInvitation=action.mode==="keyboard"?false:state.showKeyboardInteractionInvitation;return {...state,interactionMode:action.mode,showKeyboardInteractionInvitation:nextKeyboardInvitation}}return state}function doChangeKeyboardInvitationVisibility(state,action){if(isUnlimitedGraphState(state)){return {...state,showKeyboardInteractionInvitation:action.shouldShow,hasBeenInteractedWith:true}}return state}function doMovePointInFigure(state,action){switch(state.type){case "segment":case "linear-system":{const newCoords=updateAtIndex({array:state.coords,index:action.figureIndex,update:tuple=>setAtIndex({array:tuple,index:action.pointIndex,newValue:boundAndSnapToGrid(action.destination,state)})});const coordsToCheck=newCoords[action.figureIndex];if(coordsOverlap(coordsToCheck)){return state}return {...state,hasBeenInteractedWith:true,coords:newCoords}}case "linear":case "ray":{const newCoords=setAtIndex({array:state.coords,index:action.pointIndex,newValue:boundAndSnapToGrid(action.destination,state)});return {...state,hasBeenInteractedWith:true,coords:newCoords}}case "angle":case "circle":throw new Error("FIXME implement circle reducer");case "none":case "point":case "polygon":case "quadratic":case "sinusoid":throw new Error(`Don't use movePointInFigure for ${state.type} graphs. Use movePoint instead!`);default:throw new UnreachableCaseError(state)}}function doMoveLine(state,action){const{snapStep,range}=state;switch(state.type){case "segment":case "linear-system":{if(action.itemIndex===undefined){throw new Error("Please provide index of line to move")}const currentLine=state.coords[action.itemIndex];if(!currentLine){throw new Error("No line to move")}const change=getChange(currentLine,action.delta,{snapStep,range});const newLine=[snap(snapStep,vec.add(currentLine[0],change)),snap(snapStep,vec.add(currentLine[1],change))];const newCoords=setAtIndex({array:state.coords,index:action.itemIndex,newValue:newLine});return {...state,type:state.type,hasBeenInteractedWith:true,coords:newCoords}}case "linear":case "ray":{const currentLine=state.coords;const change=getChange(currentLine,action.delta,{snapStep,range});const newLine=[snap(snapStep,vec.add(currentLine[0],change)),snap(snapStep,vec.add(currentLine[1],change))];return {...state,type:state.type,hasBeenInteractedWith:true,coords:newLine}}default:return state}}function doMoveAll(state,action){const{snapStep,range}=state;switch(state.type){case "polygon":{let newCoords;if(state.snapTo==="sides"||state.snapTo==="angles"){const change=getChange(state.coords,action.delta,{snapStep:[0,0],range});newCoords=state.coords.map(point=>vec.add(point,change));}else {const change=getChange(state.coords,action.delta,{snapStep,range});newCoords=state.coords.map(point=>snap(snapStep,vec.add(point,change)));}return {...state,hasBeenInteractedWith:true,coords:newCoords}}default:return state}}function doMovePoint(state,action){switch(state.type){case "angle":const newState=(()=>{if(action.index===1){const updatedCoords=boundAndSnapAngleVertex(state,action);return {...state,hasBeenInteractedWith:true,coords:updatedCoords}}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundAndSnapAngleEndPoints(action.destination,state,action.index)})}})();if(angleSidePointsTooCloseToVertex(newState)){return state}return newState;case "polygon":let newValue;if(state.snapTo==="sides"){newValue=boundAndSnapToSides(action.destination,state,action.index);}else if(state.snapTo==="angles"){newValue=boundAndSnapToPolygonAngle(action.destination,state,action.index);}else {newValue=boundAndSnapToGrid(action.destination,state);}const newCoords=setAtIndex({array:state.coords,index:action.index,newValue:newValue});const polygonSidesCanIntersect=state.numSides==="unlimited"&&!state.closedPolygon;if(!polygonSidesCanIntersect&&polygonSidesIntersect(newCoords)){return state}return {...state,hasBeenInteractedWith:true,coords:newCoords};case "point":{return {...state,hasBeenInteractedWith:true,focusedPointIndex:action.index,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundToEdgeAndSnapToGrid(action.destination,state)})}}case "sinusoid":{const destination=action.destination;const boundDestination=boundAndSnapToGrid(destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination})}}case "quadratic":{const newCoords=[...state.coords];const boundDestination=boundAndSnapToGrid(action.destination,state);newCoords[action.index]=boundDestination;const QuadraticCoefficients=getQuadraticCoefficients$2(newCoords);if(QuadraticCoefficients===undefined){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination})}}default:throw new Error("The movePoint action is only for point, quadratic, and polygon graphs")}}function doMoveCenter(state,action){switch(state.type){case "circle":{const constrainedCenter=boundAndSnapToGrid(action.destination,state);const newRadiusPoint=[...vec.add(state.radiusPoint,vec.sub(constrainedCenter,state.center))];const[xMin,xMax]=state.range[X];const[radX]=newRadiusPoint;if(radX<xMin||radX>xMax){const xJumpDist=(radX-constrainedCenter[X])*2;const possibleNewX=radX-xJumpDist;if(possibleNewX>=xMin&&possibleNewX<=xMax){newRadiusPoint[X]=possibleNewX;}}return {...state,hasBeenInteractedWith:true,center:constrainedCenter,radiusPoint:newRadiusPoint}}default:throw new Error("The doMoveCenter action is only for circle graphs")}}function doMoveRadiusPoint(state,action){switch(state.type){case "circle":{const[xMin,xMax]=state.range[X];const nextRadiusPoint=snap(state.snapStep,[clamp(action.destination[X]+0,xMin,xMax),state.center[1]]);if(_.isEqual(nextRadiusPoint,state.center)){return state}return {...state,hasBeenInteractedWith:true,radiusPoint:nextRadiusPoint}}default:throw new Error("The doMoveRadiusPoint action is only for circle graphs")}}function doChangeSnapStep(state,action){if(_.isEqual(state.snapStep,action.snapStep)){return state}return {...state,snapStep:action.snapStep}}function doChangeRange(state,action){if(_.isEqual(state.range,action.range)){return state}return {...state,range:action.range}}function doAddPoint(state,action){if(!isUnlimitedGraphState(state)){return state}const{snapStep}=state;const snappedPoint=snap(snapStep,action.location);for(const point of state.coords){if(point[X]===snappedPoint[X]&&point[Y]===snappedPoint[Y]){return state}}const newCoords=[...state.coords,snappedPoint];return {...state,hasBeenInteractedWith:true,coords:newCoords,showRemovePointButton:true,focusedPointIndex:newCoords.length-1}}function doRemovePoint(state,action){if(!isUnlimitedGraphState(state)){return state}const nextFocusedPointIndex=state.coords.length>1?state.coords.length-2:null;return {...state,coords:state.coords.filter((_,i)=>i!==action.index),focusedPointIndex:nextFocusedPointIndex,showRemovePointButton:nextFocusedPointIndex!==null?true:false}}const getDeltaVertex=(maxMoves,minMoves,delta)=>{const[deltaX,deltaY]=delta;const maxXMove=Math.min(...maxMoves.map(move=>move[X]));const maxYMove=Math.min(...maxMoves.map(move=>move[Y]));const minXMove=Math.max(...minMoves.map(move=>move[X]));const minYMove=Math.max(...minMoves.map(move=>move[Y]));const dx=clamp(deltaX,minXMove,maxXMove);const dy=clamp(deltaY,minYMove,maxYMove);return [dx,dy]};const getChange=(coords,delta,constraintOpts)=>{const maxMoves=coords.map(point=>maxMove({...constraintOpts,point}));const minMoves=coords.map(point=>minMove({...constraintOpts,point}));const[dx,dy]=getDeltaVertex(maxMoves,minMoves,delta);return [dx,dy]};function leq(a,b){return a<b||approximateEqual(a,b)}function boundAndSnapToGrid(point,{snapStep,range}){return snap(snapStep,bound$1({snapStep,range,point}))}function boundToEdgeAndSnapToGrid(point,{snapStep,range}){return snap(snapStep,boundToEdge({range,point}))}function boundAndSnapAngleVertex({range,coords,snapStep},{destination}){const coordsCopy=[...coords];const startingVertex=coordsCopy[1];const insetAmount=vec.add(snapStep,[minDistanceBetweenAngleVertexAndSidePoint,minDistanceBetweenAngleVertexAndSidePoint]);const newVertex=clampToBox(inset(insetAmount,range),snap(snapStep,destination));const delta=vec.add(newVertex,reverseVector(startingVertex));const newPoints={};for(const i of [0,2]){const oldPoint=coordsCopy[i];let newPoint=vec.add(oldPoint,delta);let angle=getAngleFromVertex(newVertex,newPoint);angle*=Math.PI/180;newPoint=constrainToBoundsOnAngle(newPoint,angle,range,snapStep);newPoints[i]=newPoint;}newPoints[1]=newVertex;Object.entries(newPoints).forEach(([i,newPoint])=>{coordsCopy[i]=newPoint;});return coordsCopy}function tooClose(point1,point2,range){const safeDistance=2;const distance=vec.dist(point1,point2);return distance<safeDistance}function constrainToBoundsOnAngle(point,angle,range,snapStep){const lower=[range[0][0]+snapStep[0],range[1][0]+snapStep[0]];const upper=[range[0][1]-snapStep[1],range[1][1]-snapStep[1]];let result=point;if(result[0]<lower[0]){result=[lower[0],result[1]+(lower[0]-result[0])*Math.tan(angle)];}else if(result[0]>upper[0]){result=[upper[0],result[1]-(result[0]-upper[0])*Math.tan(angle)];}if(result[1]<lower[1]){result=[result[0]+(lower[1]-result[1])/Math.tan(angle),lower[1]];}else if(result[1]>upper[1]){result=[result[0]-(result[1]-upper[1])/Math.tan(angle),upper[1]];}return result}function boundAndSnapAngleEndPoints(destinationPoint,{range,coords,snapDegrees,angleOffsetDeg,snapStep},index){const snap=snapDegrees||1;const offsetDegrees=angleOffsetDeg||0;const coordsCopy=[...coords];const angleRange=[[range[0][0]+snapStep[0],range[0][1]-snapStep[0]],[range[1][0]+snapStep[1],range[1][1]-snapStep[1]]];const boundPoint=bound$1({snapStep:[0,0],range:angleRange,point:destinationPoint});coordsCopy[index]=boundPoint;const vertex=coords[1];let angle=getAngleFromVertex(coordsCopy[index],vertex);angle=Math.round((angle-offsetDegrees)/snap)*snap+offsetDegrees;const minDistance=minDistanceBetweenAngleVertexAndSidePoint+.01;const distance=Math.max(vec.dist(coordsCopy[index],vertex),minDistance);const snappedValue=vec.add(vertex,polar(distance,angle));return snappedValue}function angleSidePointsTooCloseToVertex(state){return tooClose(state.coords[0],state.coords[1],state.range)||tooClose(state.coords[2],state.coords[1],state.range)}function boundAndSnapToPolygonAngle(destinationPoint,{range,coords},index){const startingPoint=coords[index];return calculateAngleSnap(destinationPoint,range,coords,index,startingPoint)}function calculateAngleSnap(destinationPoint,range,coords,index,startingPoint){const coordsCopy=[...coords];coordsCopy[index]=bound$1({snapStep:[0,0],range,point:destinationPoint});const angles=angleMeasures(coordsCopy).map(angle=>angle*180/Math.PI);const rel=j=>{return (index+j+coordsCopy.length)%coordsCopy.length};_.each([-1,1],function(j){angles[rel(j)]=Math.round(angles[rel(j)]);});const getAngle=function(a,vertex,b){const angle=getClockwiseAngle$1([coordsCopy[rel(a)],coordsCopy[rel(vertex)],coordsCopy[rel(b)]]);return angle};const innerAngles=[angles[rel(-1)]-getAngle(-2,-1,1),angles[rel(1)]-getAngle(-1,1,2)];innerAngles[2]=180-(innerAngles[0]+innerAngles[1]);if(innerAngles.some(function(angle){return leq(angle,1)})){return startingPoint}const knownSide=magnitude$1(vector$1(coordsCopy[rel(-1)],coordsCopy[rel(1)]));const onLeft=sign(ccw(coordsCopy[rel(-1)],coordsCopy[rel(1)],coordsCopy[index]))===1;const side=Math.sin(innerAngles[1]*Math.PI/180)/Math.sin(innerAngles[2]*Math.PI/180)*knownSide;const outerAngle=getAngleFromVertex(coordsCopy[rel(1)],coordsCopy[rel(-1)]);const offset=polar(side,outerAngle+(onLeft?1:-1)*innerAngles[0]);return vector$3.add(coordsCopy[rel(-1)],offset)}function boundAndSnapToSides(destinationPoint,{range,coords},index){const startingPoint=coords[index];return calculateSideSnap(destinationPoint,range,coords,index,startingPoint)}function calculateSideSnap(destinationPoint,range,coords,index,startingPoint){const boundedDestinationPoint=bound$1({snapStep:[0,0],range,point:destinationPoint});const rel=j=>{return (index+j+coords.length)%coords.length};const sides=_.map([[coords[rel(-1)],boundedDestinationPoint],[boundedDestinationPoint,coords[rel(1)]],[coords[rel(-1)],coords[rel(1)]]],function(coords){return magnitude$1(vector$1(...coords))});_.each([0,1],function(j){sides[j]=Math.round(sides[j]);});if(leq(sides[1]+sides[2],sides[0])||leq(sides[0]+sides[2],sides[1])||leq(sides[0]+sides[1],sides[2])){return startingPoint}const innerAngle=lawOfCosines(sides[0],sides[2],sides[1]);const outerAngle=getAngleFromVertex(coords[rel(1)],coords[rel(-1)]);const onLeft=sign(ccw(coords[rel(-1)],coords[rel(1)],boundedDestinationPoint))===1;const offset=polar(sides[0],outerAngle+(onLeft?1:-1)*innerAngle);return vector$3.add(coords[rel(-1)],offset)}function maxMove({snapStep,range,point}){const topRight=bound$1({snapStep,range,point:[Infinity,Infinity]});return vec.sub(topRight,point)}function minMove({snapStep,range,point}){const bottomLeft=bound$1({snapStep,range,point:[-Infinity,-Infinity]});return vec.sub(bottomLeft,point)}const coordsOverlap=coords=>coords.some((coord,i)=>coords.some((c,j)=>i!==j&&vector$3.equal(coord,c)));function updateAtIndex(args){const{array,index,update}=args;const newValue=update(array[index]);return setAtIndex({array,index,newValue})}function setAtIndex(args){const{array,index,newValue}=args;const copy=[...array];copy[index]=newValue;return copy}
1989
1990
 
1990
- const{clockwise}=geometry;const{convertRadiansToDegrees}=angles;function renderPolygonGraph(state,dispatch,i18n,markings){return {graph:jsxRuntimeExports.jsx(PolygonGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getPolygonGraphDescription(state,i18n,markings)}}const PolygonGraph=props=>{const{dispatch}=props;const{numSides,coords,snapStep,snapTo="grid"}=props.graphState;const graphConfig=useGraphConfig();const polygonRef=React.useRef(null);const pointsRef=React.useRef([]);const lastMoveTimeRef=React.useRef(0);const{range:[x,y]}=graphConfig;const[[left,top]]=useTransformVectorsToPixels([x[0],y[1]]);const points=coords??[[0,0]];const dragReferencePoint=points[0];const constrain=getKeyboardMovementConstraintForPolygon(snapStep,snapTo);const{dragging}=useDraggable({gestureTarget:polygonRef,point:dragReferencePoint,onMove:newPoint=>{const delta=vec.sub(newPoint,dragReferencePoint);dispatch(actions.polygon.moveAll(delta));},constrainKeyboardMovement:constrain});const[hovered,setHovered]=React.useState(false);const[focusVisible,setFocusVisible]=React.useState(false);React.useEffect(()=>{const focusedIndex=props.graphState.focusedPointIndex;if(focusedIndex!=null){pointsRef.current[focusedIndex]?.focus();}},[props.graphState.focusedPointIndex,props.graphState.coords.length,pointsRef]);React.useEffect(()=>{if(numSides==="unlimited"&&props.graphState.coords.length>2){dispatch(actions.polygon.closePolygon());}},[]);const statefulProps={...props,graphConfig,polygonRef,pointsRef,lastMoveTimeRef,left,top,dragging,points,hovered,setHovered,focusVisible,setFocusVisible};return numSides==="unlimited"?jsxRuntimeExports.jsx(UnlimitedPolygonGraph,{...statefulProps}):jsxRuntimeExports.jsx(LimitedPolygonGraph,{...statefulProps})};const LimitedPolygonGraph=statefulProps=>{const{dispatch,hovered,setHovered,focusVisible,setFocusVisible,graphConfig,polygonRef,lastMoveTimeRef,dragging,points}=statefulProps;const{showAngles,showSides,range,snapTo="grid",snapStep}=statefulProps.graphState;const{disableKeyboardInteraction,interactiveColor}=graphConfig;const{strings,locale}=usePerseusI18n();const id=React.useId();const pointsOffArray=Array(points.length).fill("off");const[ariaLives,setAriaLives]=React.useState(["off",...pointsOffArray]);const lines=getLines(points);const polygonPointsNumId=id+"-points-num";const polygonPointsId=id+"-points";const{srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints,srPolygonElementsNum}=describePolygonGraph(statefulProps.graphState,{strings,locale},statefulProps.graphConfig.markings);return jsxRuntimeExports.jsxs("g",{"aria-label":srPolygonGraph,"aria-describedby":`${polygonPointsNumId} ${polygonPointsId}`,children:[jsxRuntimeExports.jsx(Polygon,{points:[...points],color:interactiveColor,svgPolygonProps:{strokeWidth:focusVisible?"var(--movable-line-stroke-weight-active)":"var(--movable-line-stroke-weight)",style:{fill:"transparent"},"aria-hidden":true}}),points.map((point,i)=>{const pt1=points.at(i-1);const pt2=points[(i+1)%points.length];if(!pt1||!pt2){return null}return jsxRuntimeExports.jsx(PolygonAngle,{centerPoint:point,endPoints:[pt1,pt2],areEndPointsClockwise:clockwise(points),showAngles:!!showAngles,snapTo:snapTo},"angle-"+i)}),showSides&&lines.map(([start,end],i)=>{const[x,y]=vec.midpoint(start,end);const length=vec.dist(start,end);const isApprox=!Number.isInteger(length);return jsxRuntimeExports.jsx(TextLabel,{x:x,y:y,children:isApprox?`≈ ${length.toFixed(snapTo==="sides"?0:1)}`:length},"side-"+i)}),jsxRuntimeExports.jsx(Polygon,{points:[...points],color:"transparent",svgPolygonProps:{ref:polygonRef,tabIndex:disableKeyboardInteraction?-1:0,strokeWidth:TARGET_SIZE,style:{cursor:dragging?"grabbing":"grab",fill:hovered?"var(--mafs-blue)":"transparent"},onMouseEnter:()=>setHovered(true),onMouseLeave:()=>setHovered(false),onKeyDownCapture:()=>{setFocusVisible(hasFocusVisible(polygonRef.current));},onFocus:()=>{setFocusVisible(hasFocusVisible(polygonRef.current));setAriaLives(()=>["polite",...pointsOffArray]);},onBlur:()=>setFocusVisible(hasFocusVisible(polygonRef.current)),className:"movable-polygon",role:"button","aria-label":srPolygonGraphPoints?`${srPolygonElementsNum} ${srPolygonGraphPoints}`:srPolygonElementsNum,"aria-live":ariaLives[0],"aria-disabled":disableKeyboardInteraction}}),points.map((point,i)=>{const angleId=`${id}-angle-${i}`;const side1Id=`${id}-point-${i}-side-1`;const side2Id=`${id}-point-${i}-side-2`;const angle=getAngleFromPoints(points,i);const angleDegree=angle?convertRadiansToDegrees(angle):null;const sidesArray=getSideLengthsFromPoints(points,i);const{pointIndex:point1Index,sideLength:side1Length}=sidesArray[0];const{pointIndex:point2Index,sideLength:side2Length}=sidesArray[1];return jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx(MovablePoint$1,{ariaDescribedBy:`${angleId} ${side1Id} ${side2Id}`,ariaLive:ariaLives[i+1],constrain:getKeyboardMovementConstraintForPoint(points,i,range,snapStep,snapTo),point:point,sequenceNumber:i+1,onMove:destination=>{const now=Date.now();const targetFPS=40;const moveThresholdTime=1e3/targetFPS;if(now-lastMoveTimeRef.current>moveThresholdTime){dispatch(actions.polygon.movePoint(i,destination));lastMoveTimeRef.current=now;}},onFocus:()=>{const newPointAriaLives=[...pointsOffArray];newPointAriaLives[i]="polite";setAriaLives(["off",...newPointAriaLives]);}}),angleDegree&&jsxRuntimeExports.jsx(SRDescInSVG,{id:angleId,children:Number.isInteger(angleDegree)?strings.srPolygonPointAngle({angle:angleDegree}):strings.srPolygonPointAngleApprox({angle:srFormatNumber(angleDegree,locale,1)})}),jsxRuntimeExports.jsx(SRDescInSVG,{id:side1Id,children:getPolygonSideString(side1Length,point1Index,strings,locale)}),jsxRuntimeExports.jsx(SRDescInSVG,{id:side2Id,children:getPolygonSideString(side2Length,point2Index,strings,locale)})]},"point-"+i)}),jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsNumId,children:srPolygonGraphPointsNum}),srPolygonGraphPoints&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsId,children:srPolygonGraphPoints})]})};const UnlimitedPolygonGraph=statefulProps=>{const{dispatch,graphConfig,left,top,pointsRef,points}=statefulProps;const{coords,closedPolygon}=statefulProps.graphState;const{strings,locale}=usePerseusI18n();const{interactiveColor}=useGraphConfig();const id=React.useId();const polygonPointsNumId=id+"-points-num";const polygonPointsId=id+"-points";const pointsOffArray=Array(points.length).fill("off");const[ariaLives,setAriaLives]=React.useState(pointsOffArray);if(closedPolygon){const closedPolygonProps={...statefulProps,numSides:coords.length};return jsxRuntimeExports.jsx(LimitedPolygonGraph,{...closedPolygonProps})}const{graphDimensionsInPixels}=graphConfig;const widthPx=graphDimensionsInPixels[0];const heightPx=graphDimensionsInPixels[1];const emptyGraph=coords.length===0;const{srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints}=describePolygonGraph(statefulProps.graphState,{strings,locale},statefulProps.graphConfig.markings);return jsxRuntimeExports.jsxs("g",{"aria-label":emptyGraph?strings.srUnlimitedPolygonEmpty:srPolygonGraph,"aria-describedby":`${polygonPointsNumId} ${polygonPointsId}`,children:[jsxRuntimeExports.jsx(Polyline,{points:[...points],color:interactiveColor,svgPolylineProps:{strokeWidth:"var(--movable-line-stroke-weight)",style:{fill:"transparent"},"aria-hidden":true}}),jsxRuntimeExports.jsx("rect",{"aria-hidden":true,style:{fill:"rgba(0,0,0,0)",cursor:"crosshair"},width:widthPx,height:heightPx,x:left,y:top,onClick:event=>{const elementRect=event.currentTarget.getBoundingClientRect();const x=event.clientX-elementRect.x;const y=event.clientY-elementRect.y;const graphCoordinates=pixelsToVectors([[x,y]],graphConfig);dispatch(actions.polygon.addPoint(graphCoordinates[0]));}}),coords.map((point,i)=>{const angleId=`${id}-angle-${i}`;let sideIds="";const hasAngle=i>0&&i<coords.length-1;const angle=hasAngle?getAngleFromPoints(points,i):null;const angleDegree=angle?convertRadiansToDegrees(angle):null;const sidesArray=getSideLengthsFromPoints(points,i,true);for(let sideIndex=0;sideIndex<sidesArray.length;sideIndex++){sideIds+=`${id}-point-${i}-side-${sideIndex} `;}return jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx(MovablePoint$1,{ariaDescribedBy:`${angleId} ${sideIds}`,ariaLive:ariaLives[i],point:point,sequenceNumber:i+1,onMove:destination=>dispatch(actions.polygon.movePoint(i,destination)),ref:ref=>{pointsRef.current[i]=ref;},onFocus:()=>{dispatch(actions.polygon.focusPoint(i));const newPointAriaLives=[...pointsOffArray];newPointAriaLives[i]="polite";setAriaLives([...newPointAriaLives]);},onClick:()=>{if(i===0&&getArrayWithoutDuplicates(coords).length>=3){dispatch(actions.polygon.closePolygon());}dispatch(actions.polygon.clickPoint(i));}}),angleDegree&&jsxRuntimeExports.jsx(SRDescInSVG,{id:angleId,children:Number.isInteger(angleDegree)?strings.srPolygonPointAngle({angle:angleDegree}):strings.srPolygonPointAngleApprox({angle:srFormatNumber(angleDegree,locale,1)})}),sidesArray.map(({pointIndex,sideLength},j)=>jsxRuntimeExports.jsx(SRDescInSVG,{id:`${id}-point-${i}-side-${j}`,children:getPolygonSideString(sideLength,pointIndex,strings,locale)},`${id}-point-${i}-side-${j}`))]},"point-"+i)}),coords.length>0&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsNumId,children:srPolygonGraphPointsNum}),srPolygonGraphPoints&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsId,children:srPolygonGraphPoints})]})};function getLines(points){return points.map((point,i)=>{const next=points[(i+1)%points.length];return [point,next]})}const hasFocusVisible=element=>{const matches=selector=>element?.matches(selector)??false;try{return matches(":focus-visible")}catch{return matches(":focus")}};function getPolygonGraphDescription(state,i18n,markings){const strings=describePolygonGraph(state,i18n,markings);return strings.srPolygonInteractiveElements}function describePolygonGraph(state,i18n,markings){const{strings,locale}=i18n;const{coords}=state;const isCoordinatePlane=markings==="axes"||markings==="graph";const hasOnePoint=coords.length===1;const srPolygonGraph=isCoordinatePlane?strings.srPolygonGraphCoordinatePlane:strings.srPolygonGraph;const srPolygonGraphPointsNum=hasOnePoint?strings.srPolygonGraphPointsOne:strings.srPolygonGraphPointsNum({num:coords.length});let srPolygonGraphPoints;if(isCoordinatePlane){const pointsString=coords.map((coord,i)=>{return strings.srPointAtCoordinates({num:i+1,x:srFormatNumber(coord[0],locale),y:srFormatNumber(coord[1],locale)})});srPolygonGraphPoints=pointsString.join(" ");}const srPolygonElementsNum=hasOnePoint?strings.srPolygonElementsOne:strings.srPolygonElementsNum({num:coords.length});const srPolygonInteractiveElements=coords.length>0?strings.srInteractiveElements({elements:[srPolygonElementsNum,srPolygonGraphPoints].join(" ")}):null;return {srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints,srPolygonElementsNum,srPolygonInteractiveElements}}function getKeyboardMovementConstraintForPoint(points,index,range,snapStep,snapTo){switch(snapTo){case "grid":return p=>snap(snapStep,p);case "sides":return getSideSnapConstraint(points,index,range);case "angles":return getAngleSnapConstraint(points,index,range);default:throw new UnreachableCaseError(snapTo)}}function getKeyboardMovementConstraintForPolygon(snapStep,snapTo){switch(snapTo){case "grid":return p=>snap(snapStep,p);case "sides":case "angles":return p=>p;default:throw new UnreachableCaseError(snapTo)}}function getSideSnapConstraint(points,index,range){const newPoints=[...points];const pointToBeMoved=newPoints[index];const movePointWithConstraint=moveFunc=>{let destinationAttempt=moveFunc(pointToBeMoved);let newPoint=pointToBeMoved;while(newPoint[0]===pointToBeMoved[0]&&newPoint[1]===pointToBeMoved[1]&&isInBound({range,point:destinationAttempt})){newPoint=calculateSideSnap(destinationAttempt,range,newPoints,index,pointToBeMoved);destinationAttempt=moveFunc(destinationAttempt);}return newPoint};return {up:movePointWithConstraint(coord=>vec.add(coord,[0,1])),down:movePointWithConstraint(coord=>vec.sub(coord,[0,1])),left:movePointWithConstraint(coord=>vec.sub(coord,[1,0])),right:movePointWithConstraint(coord=>vec.add(coord,[1,0]))}}function getAngleSnapConstraint(points,index,range){const newPoints=[...points];const pointToBeMoved=newPoints[index];const movePointWithConstraint=moveFunc=>{let destinationAttempt=bound$1({snapStep:[0,0],range,point:moveFunc(pointToBeMoved)});let newPoint=pointToBeMoved;while(newPoint[0]===pointToBeMoved[0]&&newPoint[1]===pointToBeMoved[1]&&isInBound({range,point:destinationAttempt})){newPoint=calculateAngleSnap(destinationAttempt,range,newPoints,index,pointToBeMoved);destinationAttempt=moveFunc(destinationAttempt);}return newPoint};return {up:movePointWithConstraint(coord=>vec.add(coord,[0,.1])),down:movePointWithConstraint(coord=>vec.sub(coord,[0,.1])),left:movePointWithConstraint(coord=>vec.sub(coord,[.1,0])),right:movePointWithConstraint(coord=>vec.add(coord,[.1,0]))}}
1991
+ const{clockwise}=geometry;const{convertRadiansToDegrees}=angles;function renderPolygonGraph(state,dispatch,i18n,markings){return {graph:jsxRuntimeExports.jsx(PolygonGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getPolygonGraphDescription(state,i18n,markings)}}const PolygonGraph=props=>{const{dispatch}=props;const{numSides,coords,snapStep,snapTo="grid"}=props.graphState;const graphConfig=useGraphConfig();const polygonRef=React.useRef(null);const pointsRef=React.useRef([]);const lastMoveTimeRef=React.useRef(0);const{range:[x,y]}=graphConfig;const[[left,top]]=useTransformVectorsToPixels([x[0],y[1]]);const points=coords??[[0,0]];const dragReferencePoint=points[0];const constrain=getKeyboardMovementConstraintForPolygon(snapStep,snapTo);const{dragging}=useDraggable({gestureTarget:polygonRef,point:dragReferencePoint,onMove:newPoint=>{const delta=vec.sub(newPoint,dragReferencePoint);dispatch(actions.polygon.moveAll(delta));},constrainKeyboardMovement:constrain});const[hovered,setHovered]=React.useState(false);const[focusVisible,setFocusVisible]=React.useState(false);React.useEffect(()=>{const focusedIndex=props.graphState.focusedPointIndex;if(focusedIndex!=null){pointsRef.current[focusedIndex]?.focus();}},[props.graphState.focusedPointIndex,props.graphState.coords.length,pointsRef]);React.useEffect(()=>{if(numSides==="unlimited"&&props.graphState.coords.length>2){dispatch(actions.polygon.closePolygon());}},[]);const statefulProps={...props,graphConfig,polygonRef,pointsRef,lastMoveTimeRef,left,top,dragging,points,hovered,setHovered,focusVisible,setFocusVisible};return numSides==="unlimited"?jsxRuntimeExports.jsx(UnlimitedPolygonGraph,{...statefulProps}):jsxRuntimeExports.jsx(LimitedPolygonGraph,{...statefulProps})};const LimitedPolygonGraph=statefulProps=>{const{dispatch,hovered,setHovered,focusVisible,setFocusVisible,graphConfig,polygonRef,lastMoveTimeRef,dragging,points}=statefulProps;const{showAngles,showSides,range,snapTo="grid",snapStep}=statefulProps.graphState;const{disableKeyboardInteraction,interactiveColor}=graphConfig;const{strings,locale}=usePerseusI18n();const id=React.useId();const pointsOffArray=Array(points.length).fill("off");const[ariaLives,setAriaLives]=React.useState(["off",...pointsOffArray]);const lines=getLines(points);const polygonPointsNumId=id+"-points-num";const polygonPointsId=id+"-points";const{srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints,srPolygonElementsNum}=describePolygonGraph(statefulProps.graphState,{strings,locale},statefulProps.graphConfig.markings);return jsxRuntimeExports.jsxs("g",{"aria-label":srPolygonGraph,"aria-describedby":`${polygonPointsNumId} ${polygonPointsId}`,children:[jsxRuntimeExports.jsx(Polygon,{points:[...points],color:interactiveColor,svgPolygonProps:{strokeWidth:focusVisible?"var(--movable-line-stroke-weight-active)":"var(--movable-line-stroke-weight)",style:{fill:"transparent"},"aria-hidden":true}}),points.map((point,i)=>{const pt1=points.at(i-1);const pt2=points[(i+1)%points.length];if(!pt1||!pt2){return null}return jsxRuntimeExports.jsx(PolygonAngle,{centerPoint:point,endPoints:[pt1,pt2],areEndPointsClockwise:clockwise(points),showAngles:!!showAngles,snapTo:snapTo},"angle-"+i)}),showSides&&lines.map(([start,end],i)=>{const[x,y]=vec.midpoint(start,end);const length=vec.dist(start,end);const isApprox=!Number.isInteger(length);return jsxRuntimeExports.jsx(TextLabel,{x:x,y:y,children:isApprox?`≈ ${length.toFixed(snapTo==="sides"?0:1)}`:length},"side-"+i)}),jsxRuntimeExports.jsx(Polygon,{points:[...points],color:"transparent",svgPolygonProps:{ref:polygonRef,tabIndex:disableKeyboardInteraction?-1:0,strokeWidth:TARGET_SIZE,style:{cursor:dragging?"grabbing":"grab",fill:hovered?"var(--mafs-blue)":"transparent"},onMouseEnter:()=>setHovered(true),onMouseLeave:()=>setHovered(false),onKeyDownCapture:()=>{setFocusVisible(hasFocusVisible(polygonRef.current));},onFocus:()=>{setFocusVisible(hasFocusVisible(polygonRef.current));setAriaLives(()=>["polite",...pointsOffArray]);},onBlur:()=>setFocusVisible(hasFocusVisible(polygonRef.current)),className:"movable-polygon",role:"button","aria-label":srPolygonGraphPoints?`${srPolygonElementsNum} ${srPolygonGraphPoints}`:srPolygonElementsNum,"aria-live":ariaLives[0],"aria-disabled":disableKeyboardInteraction}}),points.map((point,i)=>{const angleId=`${id}-angle-${i}`;const side1Id=`${id}-point-${i}-side-1`;const side2Id=`${id}-point-${i}-side-2`;const angle=getAngleFromPoints(points,i);const angleDegree=angle?convertRadiansToDegrees(angle):null;const sidesArray=getSideLengthsFromPoints(points,i);const{pointIndex:point1Index,sideLength:side1Length}=sidesArray[0];const{pointIndex:point2Index,sideLength:side2Length}=sidesArray[1];return jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx(MovablePoint$1,{ariaDescribedBy:`${angleId} ${side1Id} ${side2Id}`,ariaLive:ariaLives[i+1],constrain:getKeyboardMovementConstraintForPoint(points,i,range,snapStep,snapTo),point:point,sequenceNumber:i+1,onMove:destination=>{const now=Date.now();const targetFPS=40;const moveThresholdTime=1e3/targetFPS;if(now-lastMoveTimeRef.current>moveThresholdTime){dispatch(actions.polygon.movePoint(i,destination));lastMoveTimeRef.current=now;}},onFocus:()=>{const newPointAriaLives=[...pointsOffArray];newPointAriaLives[i]="polite";setAriaLives(["off",...newPointAriaLives]);}}),angleDegree&&jsxRuntimeExports.jsx(SRDescInSVG,{id:angleId,children:Number.isInteger(angleDegree)?strings.srPolygonPointAngle({angle:angleDegree}):strings.srPolygonPointAngleApprox({angle:srFormatNumber(angleDegree,locale,1)})}),jsxRuntimeExports.jsx(SRDescInSVG,{id:side1Id,children:getPolygonSideString(side1Length,point1Index,strings,locale)}),jsxRuntimeExports.jsx(SRDescInSVG,{id:side2Id,children:getPolygonSideString(side2Length,point2Index,strings,locale)})]},"point-"+i)}),jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsNumId,children:srPolygonGraphPointsNum}),srPolygonGraphPoints&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsId,children:srPolygonGraphPoints})]})};const UnlimitedPolygonGraph=statefulProps=>{const{dispatch,graphConfig,left,top,pointsRef,points}=statefulProps;const{coords,closedPolygon}=statefulProps.graphState;const{strings,locale}=usePerseusI18n();const{interactiveColor}=useGraphConfig();const[isCurrentlyDragging,setIsCurrentlyDragging]=useState(false);const dragEndCallbackTimer=useTimeout(()=>setIsCurrentlyDragging(false),400);const id=React.useId();const polygonPointsNumId=id+"-points-num";const polygonPointsId=id+"-points";const pointsOffArray=Array(points.length).fill("off");const[ariaLives,setAriaLives]=React.useState(pointsOffArray);if(closedPolygon){const closedPolygonProps={...statefulProps,numSides:coords.length};return jsxRuntimeExports.jsx(LimitedPolygonGraph,{...closedPolygonProps})}const{graphDimensionsInPixels}=graphConfig;const widthPx=graphDimensionsInPixels[0];const heightPx=graphDimensionsInPixels[1];const emptyGraph=coords.length===0;const{srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints}=describePolygonGraph(statefulProps.graphState,{strings,locale},statefulProps.graphConfig.markings);return jsxRuntimeExports.jsxs("g",{"aria-label":emptyGraph?strings.srUnlimitedPolygonEmpty:srPolygonGraph,"aria-describedby":`${polygonPointsNumId} ${polygonPointsId}`,children:[jsxRuntimeExports.jsx(Polyline,{points:[...points],color:interactiveColor,svgPolylineProps:{strokeWidth:"var(--movable-line-stroke-weight)",style:{fill:"transparent"},"aria-hidden":true}}),jsxRuntimeExports.jsx("rect",{"aria-hidden":true,style:{fill:"rgba(0,0,0,0)",cursor:"crosshair"},width:widthPx,height:heightPx,x:left,y:top,onClick:event=>{if(isCurrentlyDragging){return}const elementRect=event.currentTarget.getBoundingClientRect();const x=event.clientX-elementRect.x;const y=event.clientY-elementRect.y;const graphCoordinates=pixelsToVectors([[x,y]],graphConfig);dispatch(actions.polygon.addPoint(graphCoordinates[0]));}}),coords.map((point,i)=>{const angleId=`${id}-angle-${i}`;let sideIds="";const hasAngle=i>0&&i<coords.length-1;const angle=hasAngle?getAngleFromPoints(points,i):null;const angleDegree=angle?convertRadiansToDegrees(angle):null;const sidesArray=getSideLengthsFromPoints(points,i,true);for(let sideIndex=0;sideIndex<sidesArray.length;sideIndex++){sideIds+=`${id}-point-${i}-side-${sideIndex} `;}return jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx(MovablePoint$1,{ariaDescribedBy:`${angleId} ${sideIds}`,ariaLive:ariaLives[i],point:point,sequenceNumber:i+1,onMove:destination=>{setIsCurrentlyDragging(true);dispatch(actions.polygon.movePoint(i,destination));},onDragEnd:()=>{dragEndCallbackTimer.set();},ref:ref=>{pointsRef.current[i]=ref;},onFocus:()=>{dispatch(actions.polygon.focusPoint(i));const newPointAriaLives=[...pointsOffArray];newPointAriaLives[i]="polite";setAriaLives([...newPointAriaLives]);},onClick:()=>{if(i===0&&getArrayWithoutDuplicates(coords).length>=3){dispatch(actions.polygon.closePolygon());}dispatch(actions.polygon.clickPoint(i));}}),angleDegree&&jsxRuntimeExports.jsx(SRDescInSVG,{id:angleId,children:Number.isInteger(angleDegree)?strings.srPolygonPointAngle({angle:angleDegree}):strings.srPolygonPointAngleApprox({angle:srFormatNumber(angleDegree,locale,1)})}),sidesArray.map(({pointIndex,sideLength},j)=>jsxRuntimeExports.jsx(SRDescInSVG,{id:`${id}-point-${i}-side-${j}`,children:getPolygonSideString(sideLength,pointIndex,strings,locale)},`${id}-point-${i}-side-${j}`))]},"point-"+i)}),coords.length>0&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsNumId,children:srPolygonGraphPointsNum}),srPolygonGraphPoints&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsId,children:srPolygonGraphPoints})]})};function getLines(points){return points.map((point,i)=>{const next=points[(i+1)%points.length];return [point,next]})}const hasFocusVisible=element=>{const matches=selector=>element?.matches(selector)??false;try{return matches(":focus-visible")}catch{return matches(":focus")}};function getPolygonGraphDescription(state,i18n,markings){const strings=describePolygonGraph(state,i18n,markings);return strings.srPolygonInteractiveElements}function describePolygonGraph(state,i18n,markings){const{strings,locale}=i18n;const{coords}=state;const isCoordinatePlane=markings==="axes"||markings==="graph";const hasOnePoint=coords.length===1;const srPolygonGraph=isCoordinatePlane?strings.srPolygonGraphCoordinatePlane:strings.srPolygonGraph;const srPolygonGraphPointsNum=hasOnePoint?strings.srPolygonGraphPointsOne:strings.srPolygonGraphPointsNum({num:coords.length});let srPolygonGraphPoints;if(isCoordinatePlane){const pointsString=coords.map((coord,i)=>{return strings.srPointAtCoordinates({num:i+1,x:srFormatNumber(coord[0],locale),y:srFormatNumber(coord[1],locale)})});srPolygonGraphPoints=pointsString.join(" ");}const srPolygonElementsNum=hasOnePoint?strings.srPolygonElementsOne:strings.srPolygonElementsNum({num:coords.length});const srPolygonInteractiveElements=coords.length>0?strings.srInteractiveElements({elements:[srPolygonElementsNum,srPolygonGraphPoints].join(" ")}):null;return {srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints,srPolygonElementsNum,srPolygonInteractiveElements}}function getKeyboardMovementConstraintForPoint(points,index,range,snapStep,snapTo){switch(snapTo){case "grid":return p=>snap(snapStep,p);case "sides":return getSideSnapConstraint(points,index,range);case "angles":return getAngleSnapConstraint(points,index,range);default:throw new UnreachableCaseError(snapTo)}}function getKeyboardMovementConstraintForPolygon(snapStep,snapTo){switch(snapTo){case "grid":return p=>snap(snapStep,p);case "sides":case "angles":return p=>p;default:throw new UnreachableCaseError(snapTo)}}function getSideSnapConstraint(points,index,range){const newPoints=[...points];const pointToBeMoved=newPoints[index];const movePointWithConstraint=moveFunc=>{let destinationAttempt=moveFunc(pointToBeMoved);let newPoint=pointToBeMoved;while(newPoint[0]===pointToBeMoved[0]&&newPoint[1]===pointToBeMoved[1]&&isInBound({range,point:destinationAttempt})){newPoint=calculateSideSnap(destinationAttempt,range,newPoints,index,pointToBeMoved);destinationAttempt=moveFunc(destinationAttempt);}return newPoint};return {up:movePointWithConstraint(coord=>vec.add(coord,[0,1])),down:movePointWithConstraint(coord=>vec.sub(coord,[0,1])),left:movePointWithConstraint(coord=>vec.sub(coord,[1,0])),right:movePointWithConstraint(coord=>vec.add(coord,[1,0]))}}function getAngleSnapConstraint(points,index,range){const newPoints=[...points];const pointToBeMoved=newPoints[index];const movePointWithConstraint=moveFunc=>{let destinationAttempt=bound$1({snapStep:[0,0],range,point:moveFunc(pointToBeMoved)});let newPoint=pointToBeMoved;while(newPoint[0]===pointToBeMoved[0]&&newPoint[1]===pointToBeMoved[1]&&isInBound({range,point:destinationAttempt})){newPoint=calculateAngleSnap(destinationAttempt,range,newPoints,index,pointToBeMoved);destinationAttempt=moveFunc(destinationAttempt);}return newPoint};return {up:movePointWithConstraint(coord=>vec.add(coord,[0,.1])),down:movePointWithConstraint(coord=>vec.sub(coord,[0,.1])),left:movePointWithConstraint(coord=>vec.sub(coord,[.1,0])),right:movePointWithConstraint(coord=>vec.add(coord,[.1,0]))}}
1991
1992
 
1992
1993
  function renderQuadraticGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.jsx(QuadraticGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getQuadraticGraphDescription(state,i18n)}}function QuadraticGraph(props){const{dispatch,graphState}=props;const{coords,snapStep}=graphState;const{interactiveColor}=useGraphConfig();const{strings,locale}=usePerseusI18n();const id=React.useId();const quadraticDirectionId=id+"-direction";const quadraticVertexId=id+"-vertex";const quadraticInterceptsId=id+"-intercepts";const coeffRef=React.useRef([0,0,0]);const coeffs=getQuadraticCoefficients$1(coords);if(coeffs!==undefined){coeffRef.current=coeffs;}const[a,b,c]=coeffRef.current;const y=x=>(a*x+b)*x+c;const{srQuadraticGraph,srQuadraticDirection,srQuadraticVertex,srQuadraticXIntercepts,srQuadraticYIntercept}=describeQuadraticGraph(graphState,{strings,locale});return jsxRuntimeExports.jsxs("g",{"aria-label":srQuadraticGraph,"aria-describedby":`${quadraticDirectionId} ${quadraticVertexId} ${quadraticInterceptsId}`,children:[jsxRuntimeExports.jsx(Plot$2.OfX,{y:y,color:interactiveColor,svgPathProps:{"aria-hidden":true}}),coords.map((coord,i)=>{const srQuadraticPoint=getQuadraticPointString(i+1,coord,strings,locale);const srVertex=srQuadraticVertex?` ${srQuadraticVertex}`:"";return jsxRuntimeExports.jsx(MovablePoint$1,{ariaLabel:`${srQuadraticPoint}${srVertex}`,point:coord,sequenceNumber:i+1,constrain:getQuadraticKeyboardConstraint(coords,snapStep,i),onMove:destination=>dispatch(actions.quadratic.movePoint(i,destination))},"point-"+i)}),srQuadraticDirection&&jsxRuntimeExports.jsx(SRDescInSVG,{id:quadraticDirectionId,children:srQuadraticDirection}),srQuadraticVertex&&jsxRuntimeExports.jsx(SRDescInSVG,{id:quadraticVertexId,children:srQuadraticVertex}),jsxRuntimeExports.jsx(SRDescInSVG,{id:quadraticInterceptsId,children:srQuadraticXIntercepts?`${srQuadraticXIntercepts} ${srQuadraticYIntercept}`:`${srQuadraticYIntercept}`})]})}const getQuadraticCoefficients$1=coords=>{const p1=coords[0];const p2=coords[1];const p3=coords[2];const denom=(p1[0]-p2[0])*(p1[0]-p3[0])*(p2[0]-p3[0]);if(denom===0){return}const a=(p3[0]*(p2[1]-p1[1])+p2[0]*(p1[1]-p3[1])+p1[0]*(p3[1]-p2[1]))/denom;const b=(p3[0]*p3[0]*(p1[1]-p2[1])+p2[0]*p2[0]*(p3[1]-p1[1])+p1[0]*p1[0]*(p2[1]-p3[1]))/denom;const c=(p2[0]*p3[0]*(p2[0]-p3[0])*p1[1]+p3[0]*p1[0]*(p3[0]-p1[0])*p2[1]+p1[0]*p2[0]*(p1[0]-p2[0])*p3[1])/denom;return [a,b,c]};function getQuadraticGraphDescription(state,i18n){const strings=describeQuadraticGraph(state,i18n);return strings.srQuadraticInteractiveElements}function describeQuadraticGraph(state,i18n){const{strings,locale}=i18n;const coeffs=getQuadraticCoefficients$1(state.coords);const[a,b,c]=coeffs??[0,0,0];const vertex=[-b/(2*a),c-b*b/(4*a)];const xIntercepts=getQuadraticXIntercepts(a,b,c);const srQuadraticGraph=strings.srQuadraticGraph;const srQuadraticFaceUp=strings.srQuadraticFaceUp;const srQuadraticFaceDown=strings.srQuadraticFaceDown;const srQuadraticDirection=a===0?undefined:a>0?srQuadraticFaceUp:srQuadraticFaceDown;const srQuadraticVertex=a!==0?getQuadraticVertexString(vertex,strings):undefined;const srQuadraticXIntercepts=xIntercepts.length===2?strings.srQuadraticTwoXIntercepts({intercept1:srFormatNumber(xIntercepts[0],locale),intercept2:srFormatNumber(xIntercepts[1],locale)}):xIntercepts.length===1?strings.srQuadraticOneXIntercept({intercept:srFormatNumber(xIntercepts[0],locale)}):undefined;const srQuadraticYIntercept=strings.srQuadraticYIntercept({intercept:srFormatNumber(c,locale)});const srQuadraticInteractiveElements=strings.srInteractiveElements({elements:strings.srQuadraticInteractiveElements({point1X:srFormatNumber(state.coords[0][0],locale),point1Y:srFormatNumber(state.coords[0][1],locale),point2X:srFormatNumber(state.coords[1][0],locale),point2Y:srFormatNumber(state.coords[1][1],locale),point3X:srFormatNumber(state.coords[2][0],locale),point3Y:srFormatNumber(state.coords[2][1],locale)})});return {srQuadraticGraph,srQuadraticDirection,srQuadraticVertex,srQuadraticXIntercepts,srQuadraticYIntercept,srQuadraticInteractiveElements}}const getQuadraticKeyboardConstraint=(coords,snapStep,pointMoved)=>{const newCoords=[coords[0],coords[1],coords[2]];const coordToBeMoved=newCoords[pointMoved];const movePointWithConstraint=moveFunc=>{let movedCoord=moveFunc(coordToBeMoved);newCoords[pointMoved]=movedCoord;if(areCoordsValid(newCoords)){return movedCoord}movedCoord=moveFunc(movedCoord);newCoords[pointMoved]=movedCoord;if(areCoordsValid(newCoords)){return movedCoord}return moveFunc(movedCoord)};return {up:vec.add(coordToBeMoved,[0,snapStep[1]]),down:vec.sub(coordToBeMoved,[0,snapStep[1]]),left:movePointWithConstraint(coord=>vec.sub(coord,[snapStep[0],0])),right:movePointWithConstraint(coord=>vec.add(coord,[snapStep[0],0]))}};const areCoordsValid=coords=>{const p1=coords[0];const p2=coords[1];const p3=coords[2];if(p1[0]===p2[0]||p2[0]===p3[0]||p1[0]===p3[0]){return false}return true};
1993
1994
 
@@ -2081,7 +2082,7 @@ var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,D
2081
2082
 
2082
2083
  const init=function(){registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
2083
2084
 
2084
- const libName="@khanacademy/perseus";const libVersion="71.0.0";addLibraryVersionToPerseusDebug(libName,libVersion);
2085
+ const libName="@khanacademy/perseus";const libVersion="71.1.1";addLibraryVersionToPerseusDebug(libName,libVersion);
2085
2086
 
2086
2087
  const apiVersion={major:12,minor:0};
2087
2088