@khanacademy/perseus 77.2.0 → 77.2.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/components/gif-image.d.ts +38 -0
- package/dist/components/svg-image.d.ts +12 -0
- package/dist/es/index.css +1 -1
- package/dist/es/index.css.map +1 -1
- package/dist/es/index.js +9 -6
- package/dist/es/index.js.map +1 -1
- package/dist/hint-renderer.d.ts +15 -2
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +99 -6
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/renderer.d.ts +3 -3
- package/dist/testing/test-dependencies.d.ts +0 -1
- package/dist/types.d.ts +2 -1
- package/dist/widget-ai-utils/categorizer/categorizer-ai-utils.d.ts +29 -0
- package/dist/widget-ai-utils/definition/definition-ai-utils.d.ts +8 -0
- package/dist/widget-ai-utils/dropdown/dropdown-ai-utils.d.ts +12 -0
- package/dist/widget-ai-utils/explanation/explanation-ai-utils.d.ts +12 -0
- package/dist/widget-ai-utils/expression/expression-ai-utils.d.ts +11 -0
- package/dist/widget-ai-utils/graded-group/graded-group-ai-utils.d.ts +15 -3
- package/dist/widget-ai-utils/graded-group-set/graded-group-set-ai-utils.d.ts +10 -0
- package/dist/widget-ai-utils/grapher/grapher-ai-utils.d.ts +35 -0
- package/dist/widget-ai-utils/group/group-ai-utils.d.ts +6 -0
- package/dist/widget-ai-utils/image/image-ai-utils.d.ts +16 -0
- package/dist/widget-ai-utils/input-number/input-number-ai-utils.d.ts +22 -0
- package/dist/widget-ai-utils/interactive-graph/interactive-graph-ai-utils.d.ts +50 -21
- package/dist/widget-ai-utils/label-image/label-image-ai-utils.d.ts +63 -0
- package/dist/widget-ai-utils/matcher/matcher-ai-utils.d.ts +40 -0
- package/dist/widget-ai-utils/matrix/matrix-ai-utils.d.ts +23 -0
- package/dist/widget-ai-utils/number-line/number-line-ai-utils.d.ts +52 -0
- package/dist/widget-ai-utils/numeric-input/prompt-utils.d.ts +17 -0
- package/dist/widget-ai-utils/orderer/orderer-ai-utils.d.ts +23 -0
- package/dist/widget-ai-utils/prompt-types.d.ts +16 -2
- package/dist/widget-ai-utils/radio/radio-ai-utils.d.ts +38 -0
- package/dist/widget-ai-utils/sorter/sorter-ai-utils.d.ts +19 -0
- package/dist/widget-ai-utils/unsupported-widget.d.ts +6 -5
- package/dist/widgets/dropdown/dropdown.d.ts +1 -1
- package/dist/widgets/expression/expression.d.ts +2 -2
- package/dist/widgets/image/components/explore-image-modal-content.d.ts +1 -1
- package/dist/widgets/interactive-graphs/interactive-graph.d.ts +1 -1
- package/dist/widgets/label-image/label-image.d.ts +1 -1
- package/dist/widgets/mock-widgets/mock-widget.d.ts +1 -1
- package/dist/widgets/numeric-input/numeric-input.class.d.ts +1 -1
- package/dist/widgets/numeric-input/numeric-input.d.ts +1 -1
- package/dist/widgets/table/table.d.ts +1 -1
- package/package.json +5 -4
package/dist/es/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import { TextField, TextArea } from '@khanacademy/wonder-blocks-form';
|
|
|
22
22
|
import * as ReactDOM from 'react-dom';
|
|
23
23
|
import ReactDOM__default from 'react-dom';
|
|
24
24
|
import { CircularSpinner } from '@khanacademy/wonder-blocks-progress-spinner';
|
|
25
|
+
import { parseGIF, decompressFrames } from 'gifuct-js';
|
|
25
26
|
import { point, KhanMath, number, vector as vector$3, geometry, line, angles, coefficients } from '@khanacademy/kmath';
|
|
26
27
|
import { entries, UnreachableCaseError, keys } from '@khanacademy/wonder-stuff-core';
|
|
27
28
|
import { ModalDialog, ModalPanel, ModalLauncher, FlexibleDialog } from '@khanacademy/wonder-blocks-modal';
|
|
@@ -1487,6 +1488,8 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
1487
1488
|
|
|
1488
1489
|
const MIN_VIEWPORT_HEIGHT=480;class FixedToResponsive extends React.Component{componentDidMount(){this._isMounted=true;if(window.innerHeight<MIN_VIEWPORT_HEIGHT){setTimeout(this._cacheViewportSize,800);}else {this._cacheViewportSize();}}componentWillUnmount(){this._isMounted=false;}render(){const aspectRatio=this.props.width/this.props.height;let{width,height}=this.props;if(this.props.constrainHeight&&this.state.viewportHeight){const maxHeight=2/3*this.state.viewportHeight;if(this.props.height>=maxHeight){height=maxHeight;width=maxHeight*aspectRatio;}}const style={maxWidth:width,maxHeight:height,aspectRatio:aspectRatio.toFixed(4)};const className=classNames$1("fixed-to-responsive",this.props.className);const container=jsxRuntimeExports.jsx("div",{className:className,style:style,"data-scale":this.props.scale,children:this.props.children});const shouldFullBleed=this.props.allowFullBleed&&this.state.viewportWidth&&width>=this.state.viewportWidth;if(shouldFullBleed){return jsxRuntimeExports.jsx("div",{style:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin},children:container})}return container}constructor(...args){super(...args),this._isMounted=false,this.state={viewportHeight:null,viewportWidth:null},this._cacheViewportSize=()=>{if(this._isMounted){this.setState({viewportHeight:Math.max(MIN_VIEWPORT_HEIGHT,window.innerHeight),viewportWidth:window.innerWidth});}};}}FixedToResponsive.defaultProps={className:"",constrainHeight:false,allowFullBleed:false};
|
|
1489
1490
|
|
|
1491
|
+
async function decodeGifFrames(src){const res=await fetch(src);if(!res.ok){return []}const buffer=await res.arrayBuffer();const gif=parseGIF(buffer);return decompressFrames(gif,true)}const GifImage=props=>{const{src,alt,width,height,scale,isPlaying,onLoop,onLoad}=props;const framesRef=React.useRef([]);const canvasRef=React.useRef(null);const hiddenCanvasRef=React.useRef(null);const animationIdRef=React.useRef(null);const currentFrameIndexRef=React.useRef(0);const lastFrameTimeRef=React.useRef(null);const latestPropsRef=React.useRef({isPlaying,onLoop,onLoad});latestPropsRef.current={isPlaying,onLoop,onLoad};const drawPatch=React.useCallback(index=>{const frames=framesRef.current;const hiddenCtx=hiddenCanvasRef.current?.getContext("2d");const displayCtx=canvasRef.current?.getContext("2d");if(!hiddenCtx||!hiddenCanvasRef.current||!displayCtx||!canvasRef.current||frames.length===0){return}const frame=frames[index];const{dims}=frame;if(index>0){const prev=frames[index-1];if(prev.disposalType===2){displayCtx.clearRect(prev.dims.left,prev.dims.top,prev.dims.width,prev.dims.height);}}hiddenCanvasRef.current.width=dims.width;hiddenCanvasRef.current.height=dims.height;const imageData=new ImageData(new Uint8ClampedArray(frame.patch),dims.width,dims.height);hiddenCtx.putImageData(imageData,0,0);displayCtx.drawImage(hiddenCanvasRef.current,dims.left,dims.top);},[]);const drawFrame=React.useCallback((index=0)=>{const frames=framesRef.current;if(frames.length===0||!canvasRef.current||!hiddenCanvasRef.current){return}const targetIndex=Math.min(index,frames.length-1);currentFrameIndexRef.current=targetIndex;const{width:nativeWidth,height:nativeHeight}=frames[0].dims;canvasRef.current.width=nativeWidth;canvasRef.current.height=nativeHeight;for(let i=0;i<=targetIndex;i++){drawPatch(i);}},[drawPatch]);const pause=React.useCallback(()=>{if(animationIdRef.current!==null){cancelAnimationFrame(animationIdRef.current);animationIdRef.current=null;}},[]);const animate=React.useCallback(timestamp=>{const frames=framesRef.current;if(frames.length===0){return}if(lastFrameTimeRef.current===null){lastFrameTimeRef.current=timestamp;drawPatch(currentFrameIndexRef.current);}const frame=frames[currentFrameIndexRef.current];const delay=frame.delay<=0?10:frame.delay;if(timestamp-lastFrameTimeRef.current>=delay){currentFrameIndexRef.current++;if(currentFrameIndexRef.current>=frames.length){currentFrameIndexRef.current=0;animationIdRef.current=null;latestPropsRef.current.onLoop();return}drawPatch(currentFrameIndexRef.current);lastFrameTimeRef.current=lastFrameTimeRef.current+delay;}animationIdRef.current=requestAnimationFrame(animate);},[drawPatch]);const play=React.useCallback(()=>{if(framesRef.current.length===0){return}lastFrameTimeRef.current=null;animationIdRef.current=requestAnimationFrame(animate);},[animate]);const restart=React.useCallback(()=>{pause();drawFrame(0);},[pause,drawFrame]);React.useEffect(()=>{let mounted=true;decodeGifFrames(src).then(frames=>{if(!mounted){return}framesRef.current=frames;drawFrame(0);latestPropsRef.current.onLoad?.();if(latestPropsRef.current.isPlaying){play();}});return ()=>{mounted=false;pause();framesRef.current=[];}},[src]);const prevIsPlayingRef=React.useRef(isPlaying);React.useEffect(()=>{const wasPlaying=prevIsPlayingRef.current;prevIsPlayingRef.current=isPlaying;if(isPlaying&&!wasPlaying){play();}if(!isPlaying&&wasPlaying){if(currentFrameIndexRef.current===0){restart();}else {pause();}}},[isPlaying,restart,play,pause,drawFrame]);const setCanvasRef=React.useCallback(canvas=>{canvasRef.current=canvas;if(canvas&&framesRef.current.length>0){drawFrame(0);}},[drawFrame]);return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("canvas",{"aria-label":alt,role:"img",ref:setCanvasRef,"data-testid":"gif-canvas",style:{width:width?width*scale:undefined,height:height?height*scale:undefined}}),jsxRuntimeExports.jsx("canvas",{"aria-hidden":true,tabIndex:-1,ref:hiddenCanvasRef,"data-testid":"gif-hidden-canvas",style:{display:"none"}})]})};
|
|
1492
|
+
|
|
1490
1493
|
function getKey$2(eventName,id){return eventName+":"+id}function getEventName$2(key){return key.split(":")[0]}const MovableHelperMethods={_fireEvent:function(listeners,...args){for(const listener of listeners){listener.call(this,...args);}},_applyConstraints:function(current,previous,extraOptions){let skipRemaining=false;return _.reduce(this.state.constraints,(memo,constraint)=>{if(memo===false){return false}if(skipRemaining){return memo}const result=constraint.call(this,memo,previous,{onSkipRemaining:()=>{skipRemaining=true;},...extraOptions});if(result===false){return false}if(point.is(result,2)){return result}if(result===true||result==null){return memo}throw new PerseusError("Constraint returned invalid result: "+result,Errors.Internal)},current,this)},draw:function(){const currState=this.cloneState();MovableHelperMethods._fireEvent.call(this,this.state.draw,currState,this.prevState);this.prevState=currState;},listen:function(eventName,id,func){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key]=this._listenerMap[key]||this.state[eventName].length;this.state[eventName][index]=func;},unlisten:function(eventName,id){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key];if(index!==undefined){this.state[eventName].splice(index,1);delete this._listenerMap[key];const keys=_.keys(this._listenerMap);_.each(keys,function(key){if(getEventName$2(key)===eventName&&this._listenerMap[key]>index){this._listenerMap[key]--;}},this);}}};
|
|
1491
1494
|
|
|
1492
1495
|
let prefixedTransform=null;function computePrefixedTransform(){const el=document.createElement("div");const prefixes=["transform","msTransform","MozTransform","WebkitTransform","OTransform"];let correctPrefix=null;_.each(prefixes,function(prefix){if(typeof el.style[prefix]!=="undefined"){correctPrefix=prefix;}});return correctPrefix}let canUse3dTransform=null;function computeCanUse3dTransform(){const el=document.createElement("div");const prefix=InteractiveUtil.getPrefixedTransform();el.style[prefix]="translateZ(0px)";return !!el.style[prefix]}const FUNCTION_ARRAY_OPTIONS=["add","modify","draw","remove","constraints","onMoveStart","onMove","onMoveEnd","onClick"];const InteractiveUtil={assert:function(isTrue,message){if(!isTrue){throw new PerseusError("Assertion Error"+(message?": "+message:""),Errors.Internal)}},createGettersFor:function(Class,defaults){_.each(_.keys(defaults),function(key){if(Class.prototype[key]===undefined){Class.prototype[key]=function(){return this.state[key]};}});},addMovableHelperMethodsTo:function(Class){_.each(MovableHelperMethods,function(methodFunc,methodName){if(Class.prototype[methodName]===undefined){Class.prototype[methodName]=methodFunc;}});},arrayify:function(funcOrArray){if(funcOrArray==null){return []}if(_.isArray(funcOrArray)){return _.filter(_.flatten(funcOrArray),_.identity)}return [funcOrArray]},normalizeOptions:function(options){const result={...options};FUNCTION_ARRAY_OPTIONS.forEach(function(eventName){if(options[eventName]!==undefined){result[eventName]=InteractiveUtil.arrayify(options[eventName]);}});return result},getPrefixedTransform:function(){prefixedTransform=prefixedTransform||computePrefixedTransform();return prefixedTransform},getCanUse3dTransform:function(){if(canUse3dTransform==null){canUse3dTransform=computeCanUse3dTransform();}return canUse3dTransform}};
|
|
@@ -1608,11 +1611,11 @@ function isGif(url){return url.endsWith(".gif")}function isSvg(url){const hasSvg
|
|
|
1608
1611
|
|
|
1609
1612
|
var styles$B = {"contentWrapper":"perseus_NqTCZY3N","imageContainer":"perseus_Ctn3miye"};
|
|
1610
1613
|
|
|
1611
|
-
const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=props=>{const i18n=usePerseusI18n();const scaleFF=isFeatureOn({apiOptions:props.apiOptions},"image-widget-upgrade-scale");const{initialFocusId,onClose,...svgProps}=props;const width=props.width;const height=props.height;const contentScale=props.scale;const imageIsSvg=isSvg(props.src);const scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);const effectiveScale=scaleFF?scale:1;const maxAvailableWidth=window.innerWidth-WB_MODAL_PADDING_TOTAL;const maxAvailableHeight=window.innerHeight-WB_MODAL_PADDING_TOTAL;const scaleWidth=maxAvailableWidth/(width*effectiveScale);const scaleHeight=maxAvailableHeight/(height*effectiveScale);const fitRatio=Math.min(scaleWidth,scaleHeight,1);const
|
|
1614
|
+
const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=props=>{const i18n=usePerseusI18n();const scaleFF=isFeatureOn({apiOptions:props.apiOptions},"image-widget-upgrade-scale");const{initialFocusId,onClose,...svgProps}=props;const width=props.width;const height=props.height;const contentScale=props.scale;const imageIsSvg=isSvg(props.src);const scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);const effectiveScale=scaleFF?scale:1;const maxAvailableWidth=window.innerWidth-WB_MODAL_PADDING_TOTAL;const maxAvailableHeight=window.innerHeight-WB_MODAL_PADDING_TOTAL;const scaleWidth=maxAvailableWidth/(width*effectiveScale);const scaleHeight=maxAvailableHeight/(height*effectiveScale);const fitRatio=Math.min(scaleWidth,scaleHeight,1);const constrainedDisplayWidth=width*fitRatio*effectiveScale;return jsxRuntimeExports.jsx(ModalDialog,{"aria-labelledby":"",style:wbStyles$2.dialog,children:jsxRuntimeExports.jsx(ModalPanel,{closeButtonVisible:false,content:jsxRuntimeExports.jsxs("div",{className:styles$B.contentWrapper,children:[jsxRuntimeExports.jsx("div",{className:styles$B.imageContainer,style:{width:constrainedDisplayWidth},children:jsxRuntimeExports.jsx("div",{className:"framework-perseus",tabIndex:0,id:initialFocusId,children:jsxRuntimeExports.jsx(SvgImage,{...svgProps,allowZoom:false,width:width,height:height,scale:effectiveScale})})}),jsxRuntimeExports.jsx(IconButton,{icon:closeIcon,onClick:onClose,"aria-label":i18n.strings.imageResetZoomAriaLabel,kind:"primary",style:wbStyles$2.closeButton})]})})})};const wbStyles$2=StyleSheet.create({dialog:{width:"auto",height:"auto",margin:sizing.size_320,"@media (max-width: 767px)":{margin:0}},closeButton:{position:"absolute",top:border$1.width.medium,right:border$1.width.medium,opacity:0,":hover":{opacity:1},":focus":{opacity:1}}});
|
|
1612
1615
|
|
|
1613
1616
|
const ZoomImageButton=props=>{const{imgSrc}=props;const i18n=usePerseusI18n();const uniqueId=React.useId().replace(/:/g,"");const zoomedImageUniqueId=`zoomed-image-${uniqueId}`;const handleClick=(event,openModal)=>{const mouseEvent=event;if(mouseEvent.metaKey||mouseEvent.ctrlKey){window.open(imgSrc,"_blank");}else {openModal();}};return jsxRuntimeExports.jsx(ModalLauncher,{initialFocusId:zoomedImageUniqueId,modal:({closeModal})=>jsxRuntimeExports.jsx(ZoomedImageView,{...props,initialFocusId:zoomedImageUniqueId,onClose:closeModal}),children:({openModal})=>jsxRuntimeExports.jsx(Clickable,{"aria-label":i18n.strings.imageZoomAriaLabel,onClick:event=>handleClick(event,openModal),style:{position:"absolute",width:"100%",height:"100%",overflow:"hidden",cursor:"zoom-in"},children:()=>{return jsxRuntimeExports.jsx(React.Fragment,{})}})})};
|
|
1614
1617
|
|
|
1615
|
-
function isImageProbablyPhotograph(imageUrl){return /\.(jpg|jpeg)$/i.test(imageUrl)}function defaultPreloader(dimensions){return jsxRuntimeExports.jsx("span",{style:{top:0,left:0,width:"100%",height:"100%",position:"absolute",minWidth:"20px",display:"flex",justifyContent:"center",alignContent:"center"},children:jsxRuntimeExports.jsx(CircularSpinner,{size:"medium"})})}class SvgImage extends React.Component{componentDidMount(){this._isMounted=true;if(Util.isLabeledSVG(this.props.src)){this.loadResources();}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.src!==nextProps.src){this._isLoadingGraphie=false;this.setState({imageLoaded:false,dataLoaded:false});}}shouldComponentUpdate(nextProps,nextState){if(!_.isEqual(this.props,nextProps)){return true}const wasLoaded=this.isLoadedInState(this.state);const nextLoaded=this.isLoadedInState(nextState);return wasLoaded!==nextLoaded}componentDidUpdate(prevProps,prevState){const wasLoaded=this.isLoadedInState(prevState);const isLoaded=this.isLoadedInState(this.state);if(Util.isLabeledSVG(this.props.src)&&!isLoaded&&!this._isLoadingGraphie){this.loadResources();}if(!wasLoaded&&isLoaded){this.props.setAssetStatus(this.props.src,true);}}componentWillUnmount(){this._isMounted=false;}isLoadedInState(state){return Util.isLabeledSVG(this.props.src)?state.imageLoaded&&state.dataLoaded:state.imageLoaded}loadResources(){this._isLoadingGraphie=true;loadGraphie(this.props.src,(data,localized)=>{this._isLoadingGraphie=false;if(this._isMounted&&data.labels&&data.range){const labelsRendered={};data.labels.forEach(label=>{labelsRendered[label.content]=false;});this.setState({dataLoaded:true,labelDataIsLocalized:localized,labelsRendered,labels:data.labels,range:data.range});}});}sizeProvided(){return this.props.width!=null&&this.props.height!=null}_tryGetPixels(value){value=value||"";if(!value.endsWith("px")){return null}return parseFloat(value)||null}render(){const imageSrc=this.props.src;const imageProps={alt:this.props.alt,title:this.props.title};const width=this.props.width&&this.props.width*this.props.scale;const height=this.props.height&&this.props.height*this.props.scale;const dimensions={width,height};const responsive=this.props.responsive&&!!(width&&height);let extraGraphie;if(this.props.extraGraphie&&this.props.extraGraphie.labels.length){extraGraphie=jsxRuntimeExports.jsx(Graphie,{box:this.props.extraGraphie.box,range:this.props.extraGraphie.range,options:{labels:this.props.extraGraphie.labels},responsive:true,addMouseLayer:false,setup:this.setupGraphie});}const preloaderBaseFunc=this.props.preloader===undefined?defaultPreloader:this.props.preloader;const preloader=preloaderBaseFunc?()=>preloaderBaseFunc(dimensions):null;if(!Util.isLabeledSVG(imageSrc)){if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,imgProps:imageProps,preloader:preloader,onUpdate:this.handleUpdate}),extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,allowFullBleed:this.props.allowFullBleed&&isImageProbablyPhotograph(imageSrc),scale:this.props.scale,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{...this.props,imgSrc:imageSrc,width:this.props.width,height:this.props.height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,preloader:preloader,imgProps:imageProps,onUpdate:this.handleUpdate})}const imageUrl=Util.getSvgUrl(imageSrc);let graphie;if(this.isLoadedInState(this.state)){let box;if(this.sizeProvided()){box=[width,height];}else if(this.state.imageDimensions){box=[this.state.imageDimensions[0]*this.props.scale,this.state.imageDimensions[1]*this.props.scale];}else {throw new PerseusError("svg-image has no dimensions",Errors.InvalidInput,{metadata:{src:this.props.src}})}graphie=jsxRuntimeExports.jsx(Graphie,{ref:"graphie",box:box,scale:[40*this.props.scale,40*this.props.scale],range:this.state.range,options:_.pick(this.state,"labels"),responsive:responsive,addMouseLayer:false,setup:this.setupGraphie});}if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie,extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,scale:this.props.scale,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{...this.props,imgSrc:imageUrl,width:this.props.width,height:this.props.height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsxs("div",{className:"unresponsive-svg-image",style:dimensions,children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie]})}constructor(props){super(props),this.onImageLoad=()=>{if(this.sizeProvided()){this.setState({imageLoaded:true});}else {Util.getImageSize(this.props.src,(width,height)=>{if(this._isMounted){this.setState({imageLoaded:true,imageDimensions:[width,height]});}});}},this.setupGraphie=(graphie,options)=>{const newLabelsRendered={};_.map(options.labels,labelData=>{const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.state.labelDataIsLocalized){const elem=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,false);getDependencies().svgImageJiptLabels.addLabel(elem,labelData.typesetAsMath);}else if(labelData.coordinates){const styling=this.props.scale!==1?{"font-size":100*this.props.scale+"%"}:null;const label=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,labelData.typesetAsMath,styling);const labelStyle=label[0].style;let labelTop=this._tryGetPixels(labelStyle.top);let labelLeft=this._tryGetPixels(labelStyle.left);if(labelTop===null||labelLeft===null){const labelPosition=label.position();labelTop=labelPosition.top;labelLeft=labelPosition.left;}const svgHeight=(this.props.height||0)*this.props.scale;const svgWidth=(this.props.width||0)*this.props.scale;label.css({top:labelTop/svgHeight*100+"%",left:labelLeft/svgWidth*100+"%"});_.each(labelData.style,(styleValue,styleName)=>{label.css(styleName,styleValue);});}newLabelsRendered[labelData.content]=true;});this.setState(prev=>({labelsRendered:{...prev.labelsRendered,...newLabelsRendered}}));},this.handleUpdate=status=>{this.props.onUpdate();if(!Util.isLabeledSVG(this.props.src)&&status==="loaded"){this.setState({imageLoaded:true});}};props.setAssetStatus(props.src,false);this._isMounted=false;this._isLoadingGraphie=false;this.state={imageLoaded:false,imageDimensions:null,dataLoaded:false,labelDataIsLocalized:false,labels:[],labelsRendered:{},range:[[0,0],[0,0]]};}}SvgImage.contextType=PerseusI18nContext;SvgImage.defaultProps={constrainHeight:false,onUpdate:()=>{},responsive:true,src:"",scale:1,zoomToFullSizeOnMobile:false,setAssetStatus:(src,status)=>{}};
|
|
1618
|
+
function isImageProbablyPhotograph(imageUrl){return /\.(jpg|jpeg)$/i.test(imageUrl)}function defaultPreloader(dimensions){return jsxRuntimeExports.jsx("span",{style:{top:0,left:0,width:"100%",height:"100%",position:"absolute",minWidth:"20px",display:"flex",justifyContent:"center",alignContent:"center"},children:jsxRuntimeExports.jsx(CircularSpinner,{size:"medium"})})}class SvgImage extends React.Component{componentDidMount(){this._isMounted=true;if(Util.isLabeledSVG(this.props.src)){this.loadResources();}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.src!==nextProps.src){this._isLoadingGraphie=false;this.setState({imageLoaded:false,dataLoaded:false});}}shouldComponentUpdate(nextProps,nextState){if(!_.isEqual(this.props,nextProps)){return true}const wasLoaded=this.isLoadedInState(this.state);const nextLoaded=this.isLoadedInState(nextState);return wasLoaded!==nextLoaded}componentDidUpdate(prevProps,prevState){const wasLoaded=this.isLoadedInState(prevState);const isLoaded=this.isLoadedInState(this.state);if(Util.isLabeledSVG(this.props.src)&&!isLoaded&&!this._isLoadingGraphie){this.loadResources();}if(!wasLoaded&&isLoaded){this.props.setAssetStatus(this.props.src,true);}}componentWillUnmount(){this._isMounted=false;}isLoadedInState(state){return Util.isLabeledSVG(this.props.src)?state.imageLoaded&&state.dataLoaded:state.imageLoaded}loadResources(){this._isLoadingGraphie=true;loadGraphie(this.props.src,(data,localized)=>{this._isLoadingGraphie=false;if(this._isMounted&&data.labels&&data.range){const labelsRendered={};data.labels.forEach(label=>{labelsRendered[label.content]=false;});this.setState({dataLoaded:true,labelDataIsLocalized:localized,labelsRendered,labels:data.labels,range:data.range});}});}sizeProvided(){return this.props.width!=null&&this.props.height!=null}_tryGetPixels(value){value=value||"";if(!value.endsWith("px")){return null}return parseFloat(value)||null}render(){const imageSrc=this.props.src;const imageProps={alt:this.props.alt,title:this.props.title};const width=this.props.width&&this.props.width*this.props.scale;const height=this.props.height&&this.props.height*this.props.scale;const dimensions={width,height};const responsive=this.props.responsive&&!!(width&&height);let extraGraphie;if(this.props.extraGraphie&&this.props.extraGraphie.labels.length){extraGraphie=jsxRuntimeExports.jsx(Graphie,{box:this.props.extraGraphie.box,range:this.props.extraGraphie.range,options:{labels:this.props.extraGraphie.labels},responsive:true,addMouseLayer:false,setup:this.setupGraphie});}const preloaderBaseFunc=this.props.preloader===undefined?defaultPreloader:this.props.preloader;const preloader=preloaderBaseFunc?()=>preloaderBaseFunc(dimensions):null;if(!Util.isLabeledSVG(imageSrc)){if(responsive){const isGifControlled=this.props.isGifPlaying!==undefined;const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[!isGifControlled&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,imgProps:imageProps,preloader:preloader,onUpdate:this.handleUpdate}),extraGraphie]}),isGifControlled&&jsxRuntimeExports.jsx(GifImage,{src:imageSrc,alt:this.props.alt,width:this.props.width,height:this.props.height,scale:this.props.scale,isPlaying:!!this.props.isGifPlaying,onLoop:this.props.onGifLoop??(()=>{}),onLoad:this.onImageLoad})]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,allowFullBleed:this.props.allowFullBleed&&isImageProbablyPhotograph(imageSrc),scale:this.props.scale,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{...this.props,imgSrc:imageSrc,width:this.props.width,height:this.props.height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsx(ImageLoader$1,{src:imageSrc,preloader:preloader,imgProps:imageProps,onUpdate:this.handleUpdate})}const imageUrl=Util.getSvgUrl(imageSrc);let graphie;if(this.isLoadedInState(this.state)){let box;if(this.sizeProvided()){box=[width,height];}else if(this.state.imageDimensions){box=[this.state.imageDimensions[0]*this.props.scale,this.state.imageDimensions[1]*this.props.scale];}else {throw new PerseusError("svg-image has no dimensions",Errors.InvalidInput,{metadata:{src:this.props.src}})}graphie=jsxRuntimeExports.jsx(Graphie,{ref:"graphie",box:box,scale:[40*this.props.scale,40*this.props.scale],range:this.state.range,options:_.pick(this.state,"labels"),responsive:responsive,addMouseLayer:false,setup:this.setupGraphie});}if(responsive){const imageContent=jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie,extraGraphie]});return jsxRuntimeExports.jsxs(FixedToResponsive,{className:"svg-image",width:width,height:height,constrainHeight:this.props.constrainHeight,scale:this.props.scale,children:[imageContent,this.props.allowZoom&&jsxRuntimeExports.jsx(ZoomImageButton,{...this.props,imgSrc:imageUrl,width:this.props.width,height:this.props.height})]})}imageProps.style=dimensions;return jsxRuntimeExports.jsxs("div",{className:"unresponsive-svg-image",style:dimensions,children:[jsxRuntimeExports.jsx(ImageLoader$1,{src:imageUrl,onLoad:this.onImageLoad,onUpdate:this.handleUpdate,preloader:preloader,imgProps:imageProps}),graphie]})}constructor(props){super(props),this.onImageLoad=()=>{if(this.sizeProvided()){this.setState({imageLoaded:true});}else {Util.getImageSize(this.props.src,(width,height)=>{if(this._isMounted){this.setState({imageLoaded:true,imageDimensions:[width,height]});}});}},this.setupGraphie=(graphie,options)=>{const newLabelsRendered={};_.map(options.labels,labelData=>{const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.state.labelDataIsLocalized){const elem=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,false);getDependencies().svgImageJiptLabels.addLabel(elem,labelData.typesetAsMath);}else if(labelData.coordinates){const styling=this.props.scale!==1?{"font-size":100*this.props.scale+"%"}:null;const label=graphie.label(labelData.coordinates,labelData.content,labelData.alignment,labelData.typesetAsMath,styling);const labelStyle=label[0].style;let labelTop=this._tryGetPixels(labelStyle.top);let labelLeft=this._tryGetPixels(labelStyle.left);if(labelTop===null||labelLeft===null){const labelPosition=label.position();labelTop=labelPosition.top;labelLeft=labelPosition.left;}const svgHeight=(this.props.height||0)*this.props.scale;const svgWidth=(this.props.width||0)*this.props.scale;label.css({top:labelTop/svgHeight*100+"%",left:labelLeft/svgWidth*100+"%"});_.each(labelData.style,(styleValue,styleName)=>{label.css(styleName,styleValue);});}newLabelsRendered[labelData.content]=true;});this.setState(prev=>({labelsRendered:{...prev.labelsRendered,...newLabelsRendered}}));},this.handleUpdate=status=>{this.props.onUpdate();if(!Util.isLabeledSVG(this.props.src)&&status==="loaded"){this.setState({imageLoaded:true});}};props.setAssetStatus(props.src,false);this._isMounted=false;this._isLoadingGraphie=false;this.state={imageLoaded:false,imageDimensions:null,dataLoaded:false,labelDataIsLocalized:false,labels:[],labelsRendered:{},range:[[0,0],[0,0]]};}}SvgImage.contextType=PerseusI18nContext;SvgImage.defaultProps={constrainHeight:false,onUpdate:()=>{},responsive:true,src:"",scale:1,zoomToFullSizeOnMobile:false,setAssetStatus:(src,status)=>{}};
|
|
1616
1619
|
|
|
1617
1620
|
class Tex extends React.Component{render(){const{TeX:BaseTeX}=getDependencies();return jsxRuntimeExports.jsx(BaseTeX,{onRender:this.handleRender,children:this.props.children})}constructor(props){super(props),this.handleRender=()=>{this.setState({rendered:true});this.props.onRender();if(!this._hasRendered){this._hasRendered=true;this.props.setAssetStatus(this.props.children,true);}};this.props.setAssetStatus(this.props.children,false);this.state={rendered:false};this._hasRendered=false;}}Tex.defaultProps={onRender:()=>{},setAssetStatus:(src,status)=>{}};
|
|
1618
1621
|
|
|
@@ -1834,7 +1837,7 @@ var components = /*#__PURE__*/Object.freeze({
|
|
|
1834
1837
|
|
|
1835
1838
|
const GifControlsButton=({isPlaying,onToggle})=>{const strings=usePerseusI18n().strings;return jsxRuntimeExports.jsx(Button,{kind:"secondary",startIcon:isPlaying?pauseIcon:playIcon,onClick:onToggle,style:{width:"fit-content"},children:isPlaying?strings.gifPauseButtonLabel:strings.gifPlayButtonLabel})};
|
|
1836
1839
|
|
|
1837
|
-
const MODAL_HEIGHT=568;function ExploreImageModalContent({backgroundImage,scale:contentScale,caption,alt,longDescription,linterContext,apiOptions,box,labels,range,zoomSize
|
|
1840
|
+
const MODAL_HEIGHT=568;function ExploreImageModalContent({backgroundImage,scale:contentScale,caption,alt,longDescription,linterContext,apiOptions,box,labels,range,zoomSize}){const[isGifPlaying,setIsGifPlaying]=React.useState(false);const context=React.useContext(PerseusI18nContext);if(!backgroundImage.url){return null}const scaleFF=isFeatureOn({apiOptions},"image-widget-upgrade-scale");const gifControlsFF=isFeatureOn({apiOptions},"image-widget-upgrade-gif-controls");const[zoomWidth,zoomHeight]=zoomSize;const imageIsGif=isGif(backgroundImage.url);const imageIsSvg=isSvg(backgroundImage.url);let scale=1;if(backgroundImage.width&&backgroundImage.height){scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);}let height=backgroundImage.height;let width=backgroundImage.width;height=Math.min(MODAL_HEIGHT,zoomHeight);width=zoomWidth/zoomHeight*height;if(scaleFF){if(backgroundImage.height&&backgroundImage.width){width=backgroundImage.width;height=backgroundImage.height;const maxScale=MODAL_HEIGHT/backgroundImage.height;scale=Math.min(scale,maxScale);}}return jsxRuntimeExports.jsxs("div",{className:styles$g.modalPanelContainer,children:[jsxRuntimeExports.jsx("div",{className:styles$g.modalImageContainer,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,allowZoom:false,alt:caption===alt?"":alt,width:width,height:height,scale:scaleFF?scale:1,preloader:apiOptions.imagePreloader,extraGraphie:{box:box,range:range,labels:labels??[]},zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,setAssetStatus:setAssetStatus,isGifPlaying:gifControlsFF&&imageIsGif?isGifPlaying:undefined,onGifLoop:gifControlsFF&&imageIsGif?()=>setIsGifPlaying(false):undefined})})}),jsxRuntimeExports.jsxs("div",{className:`perseus-image-modal-description ${styles$g.modalDescriptionContainer}`,children:[gifControlsFF&&imageIsGif&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(GifControlsButton,{isPlaying:isGifPlaying,onToggle:()=>setIsGifPlaying(!isGifPlaying)}),jsxRuntimeExports.jsx("div",{className:styles$g.spacerVertical})]}),caption&&jsxRuntimeExports.jsx("div",{className:styles$g.modalCaptionContainer,children:jsxRuntimeExports.jsx(Renderer,{content:caption,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),jsxRuntimeExports.jsx(Heading,{size:"large",tag:"h2",style:wbStyles$1.descriptionHeading,children:context.strings.imageDescriptionLabel}),jsxRuntimeExports.jsx(Renderer,{content:longDescription,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})]})]})}const wbStyles$1={descriptionHeading:{marginBlockEnd:sizing.size_160}};
|
|
1838
1841
|
|
|
1839
1842
|
const ExploreImageModal=props=>{const context=React__default.useContext(PerseusI18nContext);const titleText=props.title||context.strings.imageAlternativeTitle;const title=jsxRuntimeExports.jsx("h1",{className:`perseus-image-modal-title ${styles$g.modalTitleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:titleText,apiOptions:props.apiOptions,linterContext:props.linterContext,strings:context.strings})});return jsxRuntimeExports.jsx("div",{className:`framework-perseus ${styles$g.modalContainer}`,children:jsxRuntimeExports.jsx(FlexibleDialog,{title:title,content:jsxRuntimeExports.jsx(ExploreImageModalContent,{...props}),styles:{root:wbStyles.root}})})};const wbStyles={root:{borderRadius:sizing.size_120,maxWidth:"100%"}};
|
|
1840
1843
|
|
|
@@ -1842,7 +1845,7 @@ const GifControlsIcon=({isPlaying,onToggle})=>{const strings=usePerseusI18n().st
|
|
|
1842
1845
|
|
|
1843
1846
|
const ImageInfoArea=props=>{const{backgroundImage,caption,longDescription,apiOptions,linterContext,isGifPlaying,setIsGifPlaying}=props;const context=React.useContext(PerseusI18nContext);const gifControlsFF=isFeatureOn({apiOptions},"image-widget-upgrade-gif-controls");if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);return jsxRuntimeExports.jsxs("div",{className:styles$g.infoAreaContainer,children:[gifControlsFF&&imageIsGif&&jsxRuntimeExports.jsx(GifControlsIcon,{isPlaying:isGifPlaying,onToggle:()=>setIsGifPlaying(!isGifPlaying)}),gifControlsFF&&imageIsGif&&longDescription&&jsxRuntimeExports.jsx("div",{className:styles$g.spacerHorizontal}),longDescription&&jsxRuntimeExports.jsx(ModalLauncher,{modal:jsxRuntimeExports.jsx(ExploreImageModal,{...props}),children:({openModal})=>jsxRuntimeExports.jsx(ExploreImageButton,{hasCaption:!!caption,onClick:openModal})}),caption&&jsxRuntimeExports.jsx("figcaption",{className:"perseus-image-caption",children:jsxRuntimeExports.jsx(Renderer,{content:caption,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})})]})};
|
|
1844
1847
|
|
|
1845
|
-
const ImageComponent=props=>{const{apiOptions,alt,backgroundImage,box,caption,longDescription,decorative,linterContext,labels,range,title,trackInteraction,widgetId}=props;const context=React.useContext(PerseusI18nContext);const{analytics}=useDependencies();const gifControlsFF=isFeatureOn({apiOptions},"image-widget-upgrade-gif-controls");const scaleFF=isFeatureOn({apiOptions},"image-widget-upgrade-scale");const[zoomSize,setZoomSize]=React.useState([backgroundImage.width||0,backgroundImage.height||0]);const[isGifPlaying,setIsGifPlaying]=React.useState(false);const[zoomWidth,zoomHeight]=zoomSize;const ignoreResultsRef=React.useRef(false);useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"image",widgetId:widgetId}});});React.useEffect(()=>{ignoreResultsRef.current=false;Util.getImageSizeModern(backgroundImage.url).then(naturalSize=>{if(ignoreResultsRef.current){return}const[naturalWidth,naturalHeight]=naturalSize;const[savedWidth,savedHeight]=[backgroundImage.width||0,backgroundImage.height||0];if(naturalWidth>savedWidth){setZoomSize([naturalWidth,naturalHeight]);}else {setZoomSize([savedWidth,savedHeight]);}});return ()=>{ignoreResultsRef.current=true;}},[backgroundImage.url,backgroundImage.width,backgroundImage.height]);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);let scale=props.scale;if(!scaleFF||scale<=0||scale===Infinity||scale===-Infinity){scale=1;}const svgImage=jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,apiOptions:apiOptions,width:scaleFF?backgroundImage.width:zoomWidth,height:scaleFF?backgroundImage.height:zoomHeight,scale:scale,preloader:apiOptions.imagePreloader,extraGraphie:{box:box,range:range,labels:labels},trackInteraction:trackInteraction,zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,allowZoom:!decorative,alt:decorative||caption===alt?"":alt,setAssetStatus:setAssetStatus})});const maxWidth=backgroundImage.width?backgroundImage.width*scale:undefined;const width=maxWidth?undefined:"fit-content";if(decorative){return jsxRuntimeExports.jsx("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:svgImage})}return jsxRuntimeExports.jsxs("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:[title&&jsxRuntimeExports.jsx("div",{className:`perseus-image-title ${styles$g.titleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:title,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),svgImage,(gifControlsFF&&imageIsGif||caption||longDescription)&&jsxRuntimeExports.jsx(ImageInfoArea,{zoomSize:zoomSize,isGifPlaying:isGifPlaying,setIsGifPlaying:setIsGifPlaying,...props})]})};
|
|
1848
|
+
const ImageComponent=props=>{const{apiOptions,alt,backgroundImage,box,caption,longDescription,decorative,linterContext,labels,range,title,trackInteraction,widgetId}=props;const context=React.useContext(PerseusI18nContext);const{analytics}=useDependencies();const gifControlsFF=isFeatureOn({apiOptions},"image-widget-upgrade-gif-controls");const scaleFF=isFeatureOn({apiOptions},"image-widget-upgrade-scale");const[zoomSize,setZoomSize]=React.useState([backgroundImage.width||0,backgroundImage.height||0]);const[isGifPlaying,setIsGifPlaying]=React.useState(false);const[zoomWidth,zoomHeight]=zoomSize;const ignoreResultsRef=React.useRef(false);useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"image",widgetId:widgetId}});});React.useEffect(()=>{ignoreResultsRef.current=false;Util.getImageSizeModern(backgroundImage.url).then(naturalSize=>{if(ignoreResultsRef.current){return}const[naturalWidth,naturalHeight]=naturalSize;const[savedWidth,savedHeight]=[backgroundImage.width||0,backgroundImage.height||0];if(naturalWidth>savedWidth){setZoomSize([naturalWidth,naturalHeight]);}else {setZoomSize([savedWidth,savedHeight]);}});return ()=>{ignoreResultsRef.current=true;}},[backgroundImage.url,backgroundImage.width,backgroundImage.height]);React.useEffect(()=>{setIsGifPlaying(false);},[backgroundImage.url]);if(!backgroundImage.url){return null}const imageIsGif=isGif(backgroundImage.url);let scale=props.scale;if(!scaleFF||scale<=0||scale===Infinity||scale===-Infinity){scale=1;}const svgImage=jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:backgroundImage.url,apiOptions:apiOptions,width:scaleFF?backgroundImage.width:zoomWidth,height:scaleFF?backgroundImage.height:zoomHeight,scale:scale,preloader:apiOptions.imagePreloader,extraGraphie:{box:box,range:range,labels:labels},trackInteraction:trackInteraction,zoomToFullSizeOnMobile:apiOptions.isMobile,constrainHeight:apiOptions.isMobile,allowFullBleed:apiOptions.isMobile,allowZoom:!decorative&&!imageIsGif,alt:decorative||caption===alt?"":alt,setAssetStatus:setAssetStatus,isGifPlaying:gifControlsFF&&imageIsGif?isGifPlaying:undefined,onGifLoop:gifControlsFF&&imageIsGif?()=>setIsGifPlaying(false):undefined})});const maxWidth=backgroundImage.width?backgroundImage.width*scale:undefined;const width=maxWidth?undefined:"fit-content";if(decorative){return jsxRuntimeExports.jsx("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:svgImage})}return jsxRuntimeExports.jsxs("figure",{className:"perseus-image-widget",style:{maxWidth:maxWidth,width:width},children:[title&&jsxRuntimeExports.jsx("div",{className:`perseus-image-title ${styles$g.titleContainer}`,children:jsxRuntimeExports.jsx(Renderer,{content:title,apiOptions:apiOptions,linterContext:linterContext,strings:context.strings})}),svgImage,(gifControlsFF&&imageIsGif||caption||longDescription)&&jsxRuntimeExports.jsx(ImageInfoArea,{zoomSize:zoomSize,isGifPlaying:isGifPlaying,setIsGifPlaying:setIsGifPlaying,...props})]})};
|
|
1846
1849
|
|
|
1847
1850
|
const defaultBoxSize=400;const defaultRange=[0,10];const defaultBackgroundImage$1={url:null,width:0,height:0};class ImageWidget extends React.Component{getPromptJSON(){return getPromptJSON$d(this.props)}render(){return jsxRuntimeExports.jsx(ImageComponent,{...this.props})}constructor(...args){super(...args),this.isWidget=true;}}ImageWidget.contextType=PerseusI18nContext;ImageWidget.defaultProps={alignment:"block",title:"",range:[defaultRange,defaultRange],box:[defaultBoxSize,defaultBoxSize],backgroundImage:defaultBackgroundImage$1,scale:1,labels:[],alt:"",longDescription:"",decorative:false,caption:"",linterContext:linterContextDefault};var Image$1 = {name:"image",displayName:"Image",widget:ImageWidget,isLintable:true};
|
|
1848
1851
|
|
|
@@ -1948,7 +1951,7 @@ function renderCircleGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.
|
|
|
1948
1951
|
|
|
1949
1952
|
const ACTIVE_MAJOR=22;const ACTIVE_MINOR=12;const INACTIVE_MAJOR=16;const INACTIVE_MINOR=6;const RING_PAD=2;const HALO_PAD=3;const FOCUS_RING_PAD=2;const GRIP_DOT_MAJOR_OFFSETS=[-3,0,3];const GRIP_DOT_MINOR_OFFSETS=[-2,2];function AsymptoteDragHandle(props){const{center,active,focused,orientation}=props;const[x,y]=center;const{interactiveColor}=useGraphConfig();const isHorizontal=orientation==="horizontal";const majorSize=active?ACTIVE_MAJOR:INACTIVE_MAJOR;const minorSize=active?ACTIVE_MINOR:INACTIVE_MINOR;const centerW=isHorizontal?majorSize:minorSize;const centerH=isHorizontal?minorSize:majorSize;const haloW=centerW+(RING_PAD+HALO_PAD)*2;const haloH=centerH+(RING_PAD+HALO_PAD)*2;const ringW=centerW+RING_PAD*2;const ringH=centerH+RING_PAD*2;const focusRingW=haloW+FOCUS_RING_PAD*2;const focusRingH=haloH+FOCUS_RING_PAD*2;const pillRadius=(isHorizontal?centerH:centerW)/2;const haloRadius=(isHorizontal?haloH:haloW)/2;const ringRadius=(isHorizontal?ringH:ringW)/2;const focusRingRadius=(isHorizontal?focusRingH:focusRingW)/2;const dotXOffsets=isHorizontal?GRIP_DOT_MAJOR_OFFSETS:GRIP_DOT_MINOR_OFFSETS;const dotYOffsets=isHorizontal?GRIP_DOT_MINOR_OFFSETS:GRIP_DOT_MAJOR_OFFSETS;return jsxRuntimeExports.jsxs("g",{"aria-hidden":true,style:{pointerEvents:"none"},children:[focused&&jsxRuntimeExports.jsx("rect",{className:"movable-asymptote-handle-focus-ring","data-testid":"asymptote-handle-focus-ring",x:x-focusRingW/2,y:y-focusRingH/2,width:focusRingW,height:focusRingH,rx:focusRingRadius,ry:focusRingRadius,stroke:interactiveColor}),jsxRuntimeExports.jsx("rect",{className:"movable-asymptote-handle-halo",x:x-haloW/2,y:y-haloH/2,width:haloW,height:haloH,rx:haloRadius,ry:haloRadius,fill:interactiveColor}),jsxRuntimeExports.jsx("rect",{className:"movable-asymptote-handle-ring",x:x-ringW/2,y:y-ringH/2,width:ringW,height:ringH,rx:ringRadius,ry:ringRadius}),jsxRuntimeExports.jsx("rect",{className:"movable-asymptote-handle","data-testid":"asymptote-handle-pill",x:x-centerW/2,y:y-centerH/2,width:centerW,height:centerH,rx:pillRadius,ry:pillRadius,fill:interactiveColor}),active&&dotYOffsets.map(dy=>dotXOffsets.map(dx=>jsxRuntimeExports.jsx("circle",{className:"movable-asymptote-handle-dot","data-testid":"asymptote-handle-dot",cx:x+dx,cy:y+dy},`${dx},${dy}`)))]})}
|
|
1950
1953
|
|
|
1951
|
-
function MovableAsymptote(props){const{start,end,mid,point,onMove,constrainKeyboardMovement,orientation,ariaLabel}=props;const{interactiveColor,disableKeyboardInteraction}=useGraphConfig();const[focused,setFocused]=React.useState(false);const[hovered,setHovered]=React.useState(false);const groupRef=React.useRef(null);const{dragging}=useDraggable({gestureTarget:groupRef,point,onMove,constrainKeyboardMovement:constrainKeyboardMovement??(p=>p)});
|
|
1954
|
+
function MovableAsymptote(props){const{start,end,mid,point,onMove,constrainKeyboardMovement,orientation,ariaLabel}=props;const{interactiveColor,disableKeyboardInteraction}=useGraphConfig();const[focused,setFocused]=React.useState(false);const[hovered,setHovered]=React.useState(false);const groupRef=React.useRef(null);const{dragging}=useDraggable({gestureTarget:groupRef,point,onMove,constrainKeyboardMovement:constrainKeyboardMovement??(p=>p)});return jsxRuntimeExports.jsxs("g",{ref:groupRef,tabIndex:disableKeyboardInteraction?-1:0,"aria-disabled":disableKeyboardInteraction,"aria-label":ariaLabel,"aria-live":"polite",className:"movable-line",style:{cursor:dragging?"grabbing":"grab"},role:"button","data-testid":"movable-asymptote",onFocus:()=>setFocused(true),onBlur:()=>setFocused(false),onMouseEnter:()=>setHovered(true),onMouseLeave:()=>setHovered(false),children:[jsxRuntimeExports.jsx(SVGLine,{start:start,end:end,style:{stroke:"transparent",strokeWidth:TARGET_SIZE}}),jsxRuntimeExports.jsx(SVGLine,{start:start,end:end,style:{stroke:interactiveColor,strokeWidth:"var(--movable-line-stroke-weight)"},className:dragging?"movable-dragging":"",testId:"movable-asymptote__line"}),jsxRuntimeExports.jsx(AsymptoteDragHandle,{center:mid,orientation:orientation,active:dragging||focused||hovered,focused:focused})]})}
|
|
1952
1955
|
|
|
1953
1956
|
const{getExponentialCoefficients: getExponentialCoefficients$1}=coefficients;function renderExponentialGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.jsx(ExponentialGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:getExponentialDescription(state,i18n)}}function ExponentialGraph(props){const{dispatch,graphState}=props;const{interactiveColor,range}=useGraphConfig();const i18n=usePerseusI18n();const id=React.useId();const descriptionId=id+"-description";const{coords,asymptote,snapStep}=graphState;const coeffRef=React.useRef({a:1,b:1,c:0});const coeffs=getExponentialCoefficients$1(coords,asymptote);if(coeffs!==undefined){coeffRef.current=coeffs;}const asymptoteY=asymptote;const yMin=range[1][0];const yMax=range[1][1];const yPadding=(yMax-yMin)*2;const{srExponentialGraph,srExponentialDescription,srExponentialPoint1,srExponentialPoint2,srExponentialAsymptote}=describeExponentialGraph(graphState,i18n);const asymptoteLeft=[range[0][0],asymptoteY];const asymptoteRight=[range[0][1],asymptoteY];const asymptoteMidX=(range[0][0]+range[0][1])/2;const asymptoteMid=[asymptoteMidX,asymptoteY];const[leftPx,rightPx,midPx]=useTransformVectorsToPixels(asymptoteLeft,asymptoteRight,asymptoteMid);return jsxRuntimeExports.jsxs("g",{"aria-label":srExponentialGraph,"aria-describedby":descriptionId,children:[jsxRuntimeExports.jsx(MovableAsymptote,{start:leftPx,end:rightPx,mid:midPx,point:asymptoteLeft,onMove:newPoint=>dispatch(actions.exponential.moveCenter(newPoint)),constrainKeyboardMovement:p=>constrainAsymptoteKeyboard$1(p,coords,snapStep),orientation:"horizontal",ariaLabel:srExponentialAsymptote}),jsxRuntimeExports.jsx(Plot$2.OfX,{y:x=>{const y=computeExponential(x,coeffRef.current);if(y<yMin-yPadding||y>yMax+yPadding){return NaN}return y},color:interactiveColor,svgPathProps:{"aria-hidden":true}}),coords.map((coord,i)=>jsxRuntimeExports.jsx(MovablePoint$1,{ariaLabel:i===0?srExponentialPoint1:srExponentialPoint2,point:coord,sequenceNumber:i+1,constrain:getExponentialKeyboardConstraint(coords,asymptote,snapStep,i,range),onMove:destination=>dispatch(actions.exponential.movePoint(i,destination))},"point-"+i)),jsxRuntimeExports.jsx(SRDescInSVG,{id:descriptionId,children:srExponentialDescription})]})}const constrainAsymptoteKeyboard$1=(p,coords,snapStep)=>constrainAsymptoteKeyboardMovement(p,coords,snapStep,"horizontal");const getExponentialKeyboardConstraint=(coords,asymptote,snapStep,pointIndex,range)=>{const otherPoint=coords[1-pointIndex];const asymptoteY=asymptote;return getAsymptoteGraphKeyboardConstraint(coords,snapStep,pointIndex,coord=>{const clamped=snap(snapStep,bound$1({snapStep,range,point:coord}));const clampedX=clamped[X];const clampedY=clamped[Y];if(coord[Y]===asymptoteY||clampedY===asymptoteY){return false}if(coord[X]===otherPoint[X]||clampedX===otherPoint[X]){return false}const currentPoint=coords[pointIndex];const currentSide=currentPoint[Y]>asymptoteY;const proposedSide=coord[Y]>asymptoteY;if(currentSide!==proposedSide){const reflectedY=2*asymptoteY-otherPoint[Y];const clampedReflectedY=snap(snapStep,bound$1({snapStep,range,point:[0,reflectedY]}))[Y];if(reflectedY===coord[Y]||clampedReflectedY===coord[Y]||clampedReflectedY===clampedY){return false}}return true})};const computeExponential=function(x,coefficients){const{a,b,c}=coefficients;return a*Math.exp(b*x)+c};function getExponentialDescription(state,i18n){const strings=describeExponentialGraph(state,i18n);return strings.srExponentialInteractiveElements}function describeExponentialGraph(state,i18n){const{strings,locale}=i18n;const{coords,asymptote}=state;const[point1,point2]=coords;const formattedPoint1={x:srFormatNumber(point1[X],locale),y:srFormatNumber(point1[Y],locale)};const formattedPoint2={x:srFormatNumber(point2[X],locale),y:srFormatNumber(point2[Y],locale)};const asymptoteYFormatted=srFormatNumber(asymptote,locale);return {srExponentialGraph:strings.srExponentialGraph,srExponentialDescription:strings.srExponentialDescription({point1X:formattedPoint1.x,point1Y:formattedPoint1.y,point2X:formattedPoint2.x,point2Y:formattedPoint2.y,asymptoteY:asymptoteYFormatted}),srExponentialAsymptote:strings.srExponentialAsymptote({asymptoteY:asymptoteYFormatted}),srExponentialPoint1:strings.srExponentialPoint1(formattedPoint1),srExponentialPoint2:strings.srExponentialPoint2(formattedPoint2),srExponentialInteractiveElements:strings.srInteractiveElements({elements:strings.srExponentialInteractiveElements({point1X:srFormatNumber(point1[X],locale),point1Y:srFormatNumber(point1[Y],locale),point2X:srFormatNumber(point2[X],locale),point2Y:srFormatNumber(point2[Y],locale),asymptoteY:asymptoteYFormatted})})}}
|
|
1954
1957
|
|
|
@@ -2058,7 +2061,7 @@ var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,D
|
|
|
2058
2061
|
|
|
2059
2062
|
const init=function(){registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
|
|
2060
2063
|
|
|
2061
|
-
const libName="@khanacademy/perseus";const libVersion="77.2.
|
|
2064
|
+
const libName="@khanacademy/perseus";const libVersion="77.2.1";addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
2062
2065
|
|
|
2063
2066
|
const apiVersion={major:12,minor:0};
|
|
2064
2067
|
|