@khanacademy/perseus-editor 31.0.0 → 31.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/article-editor.d.ts +5 -0
- package/dist/components/alignment-select.d.ts +3 -1
- package/dist/components/widget-editor-settings.d.ts +24 -0
- package/dist/components/widget-editor.d.ts +2 -1
- package/dist/editor-page.d.ts +5 -0
- package/dist/editor.d.ts +5 -0
- package/dist/es/index.css +1 -1
- package/dist/es/index.css.map +1 -1
- package/dist/es/index.js +36 -22
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +37 -21
- package/dist/index.js.map +1 -1
- package/dist/preview/message-types.d.ts +10 -26
- package/dist/preview/use-preview-controller.d.ts +43 -0
- package/dist/preview/use-preview-presenter.d.ts +50 -0
- package/dist/testing/feature-flags-util.d.ts +2 -8
- package/dist/widgets/interactive-graph-editor/interactive-graph-editor.d.ts +135 -76
- package/dist/widgets/interactive-graph-editor/locked-figures/labeled-row.d.ts +1 -0
- package/dist/widgets/radio/editor.d.ts +4 -0
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -27,6 +27,8 @@ var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
|
|
|
27
27
|
var caretRight = require('@phosphor-icons/core/bold/caret-right-bold.svg');
|
|
28
28
|
var IconButton = require('@khanacademy/wonder-blocks-icon-button');
|
|
29
29
|
var $ = require('jquery');
|
|
30
|
+
var Link$1 = require('@khanacademy/wonder-blocks-link');
|
|
31
|
+
var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
|
|
30
32
|
var katex = require('katex');
|
|
31
33
|
var classNames = require('classnames');
|
|
32
34
|
var invariant = require('tiny-invariant');
|
|
@@ -34,10 +36,10 @@ var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
|
|
|
34
36
|
var axeCore = require('axe-core');
|
|
35
37
|
var keypadContext = require('@khanacademy/keypad-context');
|
|
36
38
|
var mathInput = require('@khanacademy/math-input');
|
|
39
|
+
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
37
40
|
var PropTypes = require('prop-types');
|
|
38
41
|
var ReactDOM = require('react-dom');
|
|
39
42
|
var KAS = require('@khanacademy/kas');
|
|
40
|
-
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
41
43
|
var wonderBlocksLabeledField = require('@khanacademy/wonder-blocks-labeled-field');
|
|
42
44
|
var plusCircle = require('@phosphor-icons/core/regular/plus-circle.svg');
|
|
43
45
|
var trashIcon$1 = require('@phosphor-icons/core/regular/trash.svg');
|
|
@@ -45,7 +47,6 @@ var kmath = require('@khanacademy/kmath');
|
|
|
45
47
|
var Banner = require('@khanacademy/wonder-blocks-banner');
|
|
46
48
|
var arrowCounterClockwise = require('@phosphor-icons/core/bold/arrow-counter-clockwise-bold.svg');
|
|
47
49
|
var perseusScore = require('@khanacademy/perseus-score');
|
|
48
|
-
var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
|
|
49
50
|
var Clickable = require('@khanacademy/wonder-blocks-clickable');
|
|
50
51
|
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
51
52
|
var pencilCircle = require('@phosphor-icons/core/regular/pencil-circle.svg');
|
|
@@ -62,7 +63,6 @@ var arrowFatLeft = require('@phosphor-icons/core/regular/arrow-fat-left.svg');
|
|
|
62
63
|
var arrowFatRight = require('@phosphor-icons/core/regular/arrow-fat-right.svg');
|
|
63
64
|
var arrowFatUp = require('@phosphor-icons/core/regular/arrow-fat-up.svg');
|
|
64
65
|
var minusCircle = require('@phosphor-icons/core/regular/minus-circle.svg');
|
|
65
|
-
var Link$1 = require('@khanacademy/wonder-blocks-link');
|
|
66
66
|
var xIcon = require('@phosphor-icons/core/regular/x.svg');
|
|
67
67
|
var checkIcon = require('@phosphor-icons/core/bold/check-bold.svg');
|
|
68
68
|
var minusCircleIcon = require('@phosphor-icons/core/bold/minus-circle-bold.svg');
|
|
@@ -102,6 +102,7 @@ var Switch__default = /*#__PURE__*/_interopDefaultCompat(Switch);
|
|
|
102
102
|
var caretRight__default = /*#__PURE__*/_interopDefaultCompat(caretRight);
|
|
103
103
|
var IconButton__default = /*#__PURE__*/_interopDefaultCompat(IconButton);
|
|
104
104
|
var $__default = /*#__PURE__*/_interopDefaultCompat($);
|
|
105
|
+
var Link__default = /*#__PURE__*/_interopDefaultCompat(Link$1);
|
|
105
106
|
var katex__default = /*#__PURE__*/_interopDefaultCompat(katex);
|
|
106
107
|
var classNames__default = /*#__PURE__*/_interopDefaultCompat(classNames);
|
|
107
108
|
var invariant__default = /*#__PURE__*/_interopDefaultCompat(invariant);
|
|
@@ -127,12 +128,11 @@ var arrowFatLeft__default = /*#__PURE__*/_interopDefaultCompat(arrowFatLeft);
|
|
|
127
128
|
var arrowFatRight__default = /*#__PURE__*/_interopDefaultCompat(arrowFatRight);
|
|
128
129
|
var arrowFatUp__default = /*#__PURE__*/_interopDefaultCompat(arrowFatUp);
|
|
129
130
|
var minusCircle__default = /*#__PURE__*/_interopDefaultCompat(minusCircle);
|
|
130
|
-
var Link__default = /*#__PURE__*/_interopDefaultCompat(Link$1);
|
|
131
131
|
var xIcon__default = /*#__PURE__*/_interopDefaultCompat(xIcon);
|
|
132
132
|
var checkIcon__default = /*#__PURE__*/_interopDefaultCompat(checkIcon);
|
|
133
133
|
var minusCircleIcon__default = /*#__PURE__*/_interopDefaultCompat(minusCircleIcon);
|
|
134
134
|
|
|
135
|
-
const libName="@khanacademy/perseus-editor";const libVersion="31.
|
|
135
|
+
const libName="@khanacademy/perseus-editor";const libVersion="31.2.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
136
136
|
|
|
137
137
|
var jsxRuntime = {exports: {}};
|
|
138
138
|
|
|
@@ -1486,31 +1486,33 @@ const IMAGE_MARKDOWN_REGEX=/!\[[^\]]*\]\([^)]+\)/g;function getFirstAvailableWid
|
|
|
1486
1486
|
|
|
1487
1487
|
const defaultItemEditorContext={question:{content:"",widgets:{},images:{}},onEditorChange:()=>{}};const ItemEditorContext=React__namespace.createContext(defaultItemEditorContext);function useItemEditorContext(){return React__namespace.useContext(ItemEditorContext)}
|
|
1488
1488
|
|
|
1489
|
-
const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext();const cta=getCtaForIssueId(issue.id,question,onEditorChange);if(!cta){return null}return jsxRuntimeExports.jsx(Button__default.default,{size:"small",onClick:cta.onClick,style:styles$
|
|
1489
|
+
const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext();const cta=getCtaForIssueId(issue.id,question,onEditorChange);if(!cta){return null}return jsxRuntimeExports.jsx(Button__default.default,{size:"small",onClick:cta.onClick,style:styles$U.button,children:cta.label},issue.id)};const styles$U={button:{marginTop:wonderBlocksTokens.sizing.size_080,marginBottom:wonderBlocksTokens.sizing.size_080}};
|
|
1490
1490
|
|
|
1491
|
-
const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(wonderBlocksCore.View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(wonderBlocksAccordion.AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$
|
|
1491
|
+
const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(wonderBlocksCore.View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(wonderBlocksAccordion.AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$T.container,containerStyle],headerStyle:[styles$T.accordionHeader,headerStyle],header:header,children:jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:[styles$T.accordionPanel,panelStyle],children:children})})})};const styles$T=aphrodite.StyleSheet.create({container:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.instructive.subtle,marginTop:wonderBlocksTokens.spacing.xSmall_8},accordionHeader:{padding:wonderBlocksTokens.spacing.small_12,paddingInlineEnd:0,height:wonderBlocksTokens.spacing.xxLarge_48},accordionPanel:{paddingTop:wonderBlocksTokens.spacing.xxSmall_6,paddingBottom:wonderBlocksTokens.spacing.xxxSmall_4,paddingLeft:wonderBlocksTokens.spacing.small_12,paddingRight:wonderBlocksTokens.spacing.small_12}});
|
|
1492
1492
|
|
|
1493
1493
|
const ShowMe=({elements})=>{const[showMe,setShowMe]=React.useState(false);if(!elements||elements.length===0){return null}const getIssueBoundary=element=>{const iframeBoundary=element.ownerDocument.defaultView?.frameElement?.getBoundingClientRect();const elementBoundary=element.getBoundingClientRect();return {top:elementBoundary.top+(iframeBoundary?.top||0),left:elementBoundary.left+(iframeBoundary?.left||0),height:elementBoundary.height,width:elementBoundary.width}};const showMeStyle={marginTop:"1em",display:"flex",alignItems:"center"};const getOutlineStyle=issueBoundary=>showMe&&issueBoundary.width!==0?{display:"block",border:"2px solid red",borderRadius:"4px",position:"fixed",height:issueBoundary.height+8,width:issueBoundary.width+8,top:issueBoundary.top-4,left:issueBoundary.left-4}:{display:"none"};const elementOutlines=elements?.map((element,index)=>{const issueBoundary=getIssueBoundary(element);const outlineStyle=getOutlineStyle(issueBoundary);return jsxRuntimeExports.jsx("div",{style:outlineStyle},index)});const showMeToggle=jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{size:"small",tag:"span",weight:"bold",style:showMeStyle,children:[jsxRuntimeExports.jsx("span",{style:{marginInlineEnd:"1em"},children:"Show Me"}),jsxRuntimeExports.jsx(Switch__default.default,{checked:showMe,onChange:setShowMe}),elementOutlines]});const showMeUnavailable=jsxRuntimeExports.jsx("div",{children:"Unable to find the offending element. Please ask a developer for help fixing this."});return Array.isArray(elementOutlines)&&elementOutlines.length>0?showMeToggle:showMeUnavailable};
|
|
1494
1494
|
|
|
1495
1495
|
const impactStringMap={high:"Error",medium:"Warning",low:"Guideline"};const IssueDetails=({issue})=>{const[expanded,setExpanded]=React__namespace.useState(false);const toggleVisibility=()=>setExpanded(!expanded);const accordionColor=issue.impact==="high"?wonderBlocksTokens.semanticColor.feedback.critical.subtle.background:wonderBlocksTokens.semanticColor.feedback.warning.subtle.background;const messageStyling={whiteSpace:"pre-line",color:wonderBlocksTokens.semanticColor.core.foreground.critical.default};return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:accordionColor},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",style:{textOverflow:"ellipsis",maxWidth:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`${impactStringMap[issue.impact]}: ${issue.id}`}),children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",weight:"bold",children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",weight:"bold",style:{marginTop:"1em"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",weight:"bold",style:{marginTop:"1em"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{style:messageStyling,children:issue.message}),jsxRuntimeExports.jsx(ShowMe,{elements:issue.elements}),jsxRuntimeExports.jsx(IssueCta,{issue:issue})]})};
|
|
1496
1496
|
|
|
1497
|
-
const LabeledSwitch
|
|
1497
|
+
const LabeledSwitch=props=>{const{checked,label,labelSide="end",size="medium",style,disabled=false,onChange}=props;const switchId=React.useId();const labelElement=jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:size==="small"?"small":undefined,tag:"label",htmlFor:switchId,children:label});const strut=jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8});return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$S.row,style],children:[labelSide==="start"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[labelElement,strut]}),jsxRuntimeExports.jsx(Switch__default.default,{id:switchId,checked:checked,disabled:disabled,onChange:onChange}),labelSide==="end"&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[strut,labelElement]})]})};const styles$S=aphrodite.StyleSheet.create({row:{flexDirection:"row",alignItems:"center"}});
|
|
1498
1498
|
|
|
1499
|
-
function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$
|
|
1499
|
+
function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$R.expanded:styles$R.collapsed;return jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{icon:caretRight__default.default,style:iconStyle})}const styles$R=aphrodite.StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
|
|
1500
1500
|
|
|
1501
|
-
const IssuesPanel=props=>{const{issues=[]}=props;const a11yCheck=props.a11yCheck||{callback:()=>{},isChecked:false};const[showPanel,setShowPanel]=React.useState(false);const hasWarnings=issues.length>0;const hasErrors=issues.some(issue=>issue.impact==="high");const issuesCount=`${issues.length} issue${issues.length===1?"":"s"}`;const icon=hasErrors?iconAlert__default.default:hasWarnings?iconWarning__default.default:iconPass__default.default;const iconColor=hasErrors?wonderBlocksTokens.semanticColor.feedback.critical.strong.icon:hasWarnings?wonderBlocksTokens.semanticColor.feedback.warning.strong.icon:wonderBlocksTokens.semanticColor.feedback.success.strong.icon;const impactOrder={high:3,medium:2,low:1};const sortedIssues=issues.sort((a,b)=>{if(impactOrder[b.impact]!==impactOrder[a.impact]){return impactOrder[b.impact]-impactOrder[a.impact]}return a.id.localeCompare(b.id)});return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:()=>setShowPanel(!showPanel),children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-content",children:[sortedIssues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{issue:issue},issue.id)),issues.length===0&&jsxRuntimeExports.jsx("div",{children:"No issues found"}),jsxRuntimeExports.jsx(LabeledSwitch
|
|
1501
|
+
const IssuesPanel=props=>{const{issues=[]}=props;const a11yCheck=props.a11yCheck||{callback:()=>{},isChecked:false};const[showPanel,setShowPanel]=React.useState(false);const hasWarnings=issues.length>0;const hasErrors=issues.some(issue=>issue.impact==="high");const issuesCount=`${issues.length} issue${issues.length===1?"":"s"}`;const icon=hasErrors?iconAlert__default.default:hasWarnings?iconWarning__default.default:iconPass__default.default;const iconColor=hasErrors?wonderBlocksTokens.semanticColor.feedback.critical.strong.icon:hasWarnings?wonderBlocksTokens.semanticColor.feedback.warning.strong.icon:wonderBlocksTokens.semanticColor.feedback.success.strong.icon;const impactOrder={high:3,medium:2,low:1};const sortedIssues=issues.sort((a,b)=>{if(impactOrder[b.impact]!==impactOrder[a.impact]){return impactOrder[b.impact]-impactOrder[a.impact]}return a.id.localeCompare(b.id)});return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:()=>setShowPanel(!showPanel),children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-content",children:[sortedIssues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{issue:issue},issue.id)),issues.length===0&&jsxRuntimeExports.jsx("div",{children:"No issues found"}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Include axe-core scan",checked:a11yCheck.isChecked,onChange:()=>{a11yCheck.callback();},style:{marginBlockStart:"1rem"}})]})})]})};
|
|
1502
1502
|
|
|
1503
1503
|
class JsonEditor extends React__namespace.Component{getInitialState(){return {currentValue:JSON.stringify(this.props.value,null,4),valid:true}}componentDidUpdate(prevProps){if(!___default.default.isEqual(prevProps.value,this.props.value)){const shouldReplaceContent=!this.state.valid||!___default.default.isEqual(this.props.value,this.getCurrentValueAsJson());if(shouldReplaceContent){this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}}getCurrentValueAsJson(){try{return this.state.currentValue?this.typesafeParseOrThrow(this.state.currentValue):{}}catch{return null}}handleKeyDown(e){if(e.key==="Tab"){const textarea=e.currentTarget;const cursorPos=textarea.selectionStart;const v=textarea.value;const textBefore=v.substring(0,cursorPos);const textAfter=v.substring(cursorPos,v.length);textarea.value=textBefore+" "+textAfter;textarea.selectionStart=textBefore.length+4;textarea.selectionEnd=textBefore.length+4;e.preventDefault();this.processChange(textarea.value);}}handleChange(e){this.processChange(e.target.value);}processChange(nextString){try{const json=this.typesafeParseOrThrow(nextString);this.setState({currentValue:nextString,valid:true},()=>{this.props.onChange(json);});}catch{this.setState({currentValue:nextString,valid:false});}}handleBlur(e){const nextString=e.target.value;try{const json=this.typesafeParseOrThrow(nextString);this.setState({currentValue:JSON.stringify(json,null,4),valid:true},()=>{this.props.onChange(json);});}catch{this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}typesafeParseOrThrow(json){const parsed=this.props.parser(json);if(perseusCore.isSuccess(parsed)){return parsed.value}const parsedFromQuotedString=this.props.parser(JSON.parse(json));if(perseusCore.isSuccess(parsedFromQuotedString)){return parsedFromQuotedString.value}throw new TypeError("JsonEditor: parse failure")}render(){const classes="perseus-json-editor "+(this.state.valid?"valid":"invalid");return jsxRuntimeExports.jsx("textarea",{className:classes,value:this.state.currentValue,onChange:this.handleChange,onKeyDown:this.handleKeyDown,onBlur:this.handleBlur,disabled:this.props.editingDisabled})}constructor(props){super(props);this.state=this.getInitialState();this.handleBlur=this.handleBlur.bind(this);this.handleChange=this.handleChange.bind(this);this.handleKeyDown=this.handleKeyDown.bind(this);}}
|
|
1504
1504
|
|
|
1505
|
-
const SectionControlButton=({icon,onClick,title,disabled})=>{return jsxRuntimeExports.jsx(IconButton__default.default,{icon:icon,disabled:disabled,"aria-label":title,style:styles$
|
|
1505
|
+
const SectionControlButton=({icon,onClick,title,disabled})=>{return jsxRuntimeExports.jsx(IconButton__default.default,{icon:icon,disabled:disabled,"aria-label":title,style:styles$Q.button,size:"xsmall",onClick:onClick})};const styles$Q=aphrodite.StyleSheet.create({button:{marginLeft:5}});
|
|
1506
1506
|
|
|
1507
1507
|
class DragTarget extends React__namespace.Component{handleDrop(e){e.stopPropagation();e.preventDefault();this.setState({dragHover:false});this.props.onDrop(e);}handleDragEnd(){this.setState({dragHover:false});}handleDragOver(e){e.preventDefault();}handleDragLeave(){this.setState({dragHover:false});}handleDragEnter(e){this.setState({dragHover:this.props.shouldDragHighlight(e)});}render(){const opacity=this.state.dragHover?{opacity:.3}:{};const{shouldDragHighlight,...forwardProps}=this.props;return jsxRuntimeExports.jsx(wonderBlocksCore.View,{...forwardProps,style:Object.assign({},this.props.style,opacity),onDrop:this.handleDrop,onDragEnd:this.handleDragEnd,onDragOver:this.handleDragOver,onDragEnter:this.handleDragEnter,onDragLeave:this.handleDragLeave})}constructor(props){super(props);this.state={dragHover:false};this.handleDrop=this.handleDrop.bind(this);this.handleDragEnd=this.handleDragEnd.bind(this);this.handleDragOver=this.handleDragOver.bind(this);this.handleDragLeave=this.handleDragLeave.bind(this);this.handleDragEnter=this.handleDragEnter.bind(this);}}DragTarget.defaultProps={shouldDragHighlight:()=>true};
|
|
1508
1508
|
|
|
1509
1509
|
function focusWithChromeStickyFocusBugWorkaround(element){element.focus({preventScroll:true});}const alignmentInfoMap={block:"Block - widget is constrained to the width of the article content container.","wrap-left":"Wrap left - widget is 50% width of the article content container, and is left aligned with text wrapping on the right of the widget.","wrap-right":"Wrap right - widget is 50% width of the article content container, and is right aligned with text wrapping on the left of the widget.","full-width":"Full width - widget extends beyond the width of the article content container."};
|
|
1510
1510
|
|
|
1511
|
-
const{InfoTip: InfoTip$p}=perseus.components;function AlignmentSelect({supportedAlignments,widgetInfo,isEditingDisabled,onChange}){return jsxRuntimeExports.jsxs(
|
|
1511
|
+
const{InfoTip: InfoTip$p}=perseus.components;function AlignmentSelect({supportedAlignments,widgetInfo,isEditingDisabled,onChange,style}){const labelId=React.useId();return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[{flexDirection:"row",alignItems:"center",gap:wonderBlocksTokens.sizing.size_080},style],children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{id:labelId,tag:"span",children:"Alignment"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{"aria-labelledby":labelId,selectedValue:widgetInfo.alignment??"default",disabled:isEditingDisabled,onChange:value=>{const syntheticEvent={currentTarget:{value}};onChange(syntheticEvent);},placeholder:"Select alignment",style:styles$P.singleSelectShort,children:supportedAlignments.map(alignment=>jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:alignment,label:alignment},alignment))}),jsxRuntimeExports.jsx(InfoTip$p,{children:jsxRuntimeExports.jsx("ul",{children:supportedAlignments.map((alignment,index)=>jsxRuntimeExports.jsx("li",{style:{marginBlockEnd:index<supportedAlignments.length-1?wonderBlocksTokens.sizing.size_240:0},children:alignmentInfoMap[alignment]},alignment))})})]})}const styles$P=aphrodite.StyleSheet.create({singleSelectShort:{height:wonderBlocksTokens.sizing.size_260}});
|
|
1512
1512
|
|
|
1513
|
-
|
|
1513
|
+
function WidgetEditorSettings(props){const{bestPractices,supportsStaticMode,isStatic,onStaticChange,supportsGradedToggle,isGraded,onGradedChange,supportedAlignments,widgetInfo,onAlignmentChange,isEditingDisabled,apiOptions}=props;const hasControls=supportsStaticMode||supportsGradedToggle||supportedAlignments.length>1;if(!bestPractices&&!hasControls){return null}const notScoredFeatureEnabled=perseusCore.isFeatureOn({apiOptions:apiOptions},"interactive-graph-not-scored");return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:"widget-editor-settings-container",children:[bestPractices&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{className:"best-practices-container",children:jsxRuntimeExports.jsx(Link__default.default,{href:bestPractices.url,target:"_blank",children:bestPractices.label})}),hasControls&&jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[supportsStaticMode&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"Static",checked:isStatic,disabled:isEditingDisabled,onChange:onStaticChange,style:{marginBlockEnd:wonderBlocksTokens.sizing.size_060}}),notScoredFeatureEnabled&&supportsGradedToggle&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"Interactive but ungraded",checked:!isGraded,disabled:isEditingDisabled,onChange:e=>{onGradedChange(!e);},style:{marginBlockEnd:wonderBlocksTokens.sizing.size_060}}),supportedAlignments.length>1&&jsxRuntimeExports.jsx(AlignmentSelect,{supportedAlignments:supportedAlignments,widgetInfo:widgetInfo,isEditingDisabled:isEditingDisabled,onChange:onAlignmentChange,style:{marginBlockEnd:wonderBlocksTokens.sizing.size_060}})]})]})}
|
|
1514
|
+
|
|
1515
|
+
const _upgradeWidgetInfo=props=>{const filteredProps=perseus.excludeDenylistKeys(props);return perseusCore.applyDefaultsToWidget(filteredProps)};class WidgetEditor extends React__namespace.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({widgetInfo:_upgradeWidgetInfo(nextProps)});if(nextProps.widgetIsOpen!=null&&nextProps.widgetIsOpen!==this.props.widgetIsOpen){this.setState({showWidget:nextProps.widgetIsOpen});}}render(){const widgetInfo=this.state.widgetInfo;const isEditingDisabled=this.props.apiOptions.editingDisabled??false;const Ed=perseus.Widgets.getEditor(widgetInfo.type);let supportedAlignments;if(this.props.apiOptions.showAlignmentOptions){supportedAlignments=perseusCore.CoreWidgetRegistry.getSupportedAlignments(widgetInfo.type);}else {supportedAlignments=["default"];}const supportsStaticMode=perseus.Widgets.supportsStaticMode(widgetInfo.type);const supportsGradedToggle=perseus.Widgets.supportsUngraded(widgetInfo.type);return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title "+(this.state.showWidget?"open":"closed"),children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:this._toggleWidget,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:this.state.showWidget}),jsxRuntimeExports.jsx("span",{children:this.props.id})]})}),jsxRuntimeExports.jsx(SectionControlButton,{icon:trashIcon__default.default,disabled:isEditingDisabled,onClick:()=>{this.props.onRemove();},title:"Remove image widget"})]}),this.state.showWidget&&jsxRuntimeExports.jsx(WidgetEditorSettings,{bestPractices:Ed?.bestPractices,supportsStaticMode:!!supportsStaticMode,isStatic:!!widgetInfo.static,onStaticChange:this._setStatic,supportsGradedToggle:supportsGradedToggle,isGraded:widgetInfo.graded!==false,onGradedChange:this._setGraded,supportedAlignments:supportedAlignments,widgetInfo:widgetInfo,onAlignmentChange:this._handleAlignmentChange,isEditingDisabled:isEditingDisabled,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-content "+(this.state.showWidget?"enter":"leave"),children:Ed&&jsxRuntimeExports.jsx(Ed,{ref:this.widget,onChange:this._handleWidgetChange,static:widgetInfo.static,graded:widgetInfo.graded,apiOptions:this.props.apiOptions,...widgetInfo.options})})]})}constructor(props){super(props),this._toggleWidget=e=>{e.preventDefault();this.setState({showWidget:!this.state.showWidget});},this._handleWidgetChange=(newProps,cb,silent)=>{const newWidgetInfo={...this.state.widgetInfo,options:{...this.state.widgetInfo.options,...this.widget.current?.serialize()??{},...newProps}};this.props.onChange(newWidgetInfo,cb,silent);},this._setStatic=value=>{const newWidgetInfo={...this.state.widgetInfo,static:value,graded:true};this.props.onChange(newWidgetInfo);},this._setGraded=value=>{const newWidgetInfo={...this.state.widgetInfo,graded:value,static:false};this.props.onChange(newWidgetInfo);},this._handleAlignmentChange=e=>{const newAlignment=e.currentTarget.value;const newWidgetInfo=Object.assign({},this.state.widgetInfo);newWidgetInfo.alignment=newAlignment;this.props.onChange(newWidgetInfo);},this.getSaveWarnings=()=>{const issuesFunc=this.widget.current?.getSaveWarnings;return issuesFunc?issuesFunc():[]},this.serialize=()=>{const widgetInfo=this.state.widgetInfo;return {type:widgetInfo.type,alignment:widgetInfo.alignment,static:widgetInfo.static,graded:widgetInfo.graded,options:this.widget.current.serialize(),version:widgetInfo.version}};this.state={showWidget:props.widgetIsOpen??true,widgetInfo:_upgradeWidgetInfo(props)};this.widget=React__namespace.createRef();}}
|
|
1514
1516
|
|
|
1515
1517
|
class WidgetSelect extends React__namespace.Component{shouldComponentUpdate(){return false}render(){const widgets=perseus.Widgets.getPublicWidgets();const orderedWidgetNames=___default.default.sortBy(___default.default.keys(widgets),name=>{return widgets[name].displayName});const addWidgetString="Add a widget…";return jsxRuntimeExports.jsxs("select",{value:"",onChange:this.handleChange,"data-testid":"editor__widget-select",children:[jsxRuntimeExports.jsx("option",{value:"",children:addWidgetString}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),orderedWidgetNames.map(name=>{return jsxRuntimeExports.jsx("option",{value:name,children:widgets[name].displayName},name)})]})}constructor(...args){super(...args),this.handleChange=e=>{const widgetType=e.currentTarget.value;if(widgetType===""){return}if(this.props.onChange){this.props.onChange(widgetType);}};}}
|
|
1516
1518
|
|
|
@@ -1574,6 +1576,18 @@ const{HUD}=perseus.components;class EditorPage extends React__namespace.Componen
|
|
|
1574
1576
|
|
|
1575
1577
|
function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice,reviewMode}){const i18n=perseus.usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(wonderBlocksCore.View,{className:`framework-perseus ${className}`,style:[styles$N.container,!seamless?styles$N.gutter:undefined],children:jsxRuntimeExports.jsx(keypadContext.StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(keypadContext.KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(perseus.UserInputManager,{widgets:question?.widgets||{},problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(perseus.Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,reviewMode:reviewMode,...question})}),jsxRuntimeExports.jsx(mathInput.MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$N=aphrodite.StyleSheet.create({container:{padding:wonderBlocksTokens.spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
|
|
1576
1578
|
|
|
1579
|
+
const PREVIEW_MESSAGE_SOURCE="perseus-preview";function createPreviewIframeReadyMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-ready"}}
|
|
1580
|
+
|
|
1581
|
+
function isIframeToParentMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&typeof message.source==="string"&&message.source===PREVIEW_MESSAGE_SOURCE}function isParentToIframeMessage(message){return typeof message==="object"&&message!==null&&"source"in message&&typeof message.source==="string"&&message.source===PREVIEW_MESSAGE_SOURCE}
|
|
1582
|
+
|
|
1583
|
+
function sanitizeApiOptions(apiOptions){if(apiOptions==null){return null}const{onFocusChange:_,answerableCallback:__,getAnotherHint:___,interactionCallback:____,imagePreloader:_____,trackInteraction:______,setDrawingAreaAvailable:________,baseElements:_________,nativeKeypadProxy:__________,imagePlaceholder:___________,widgetPlaceholder:____________,...serializableOptions}=apiOptions;return serializableOptions}
|
|
1584
|
+
|
|
1585
|
+
function sanitizePreviewData(content){if((content.type==="question"||content.type==="hint"||content.type==="article")&&content.data.apiOptions!=null){return {...content,data:{...content.data,apiOptions:sanitizeApiOptions(content.data.apiOptions)}}}if(content.type==="article-all"){return {...content,data:content.data.map(section=>section.apiOptions!=null?{...section,apiOptions:sanitizeApiOptions(section.apiOptions)}:section)}}return content}
|
|
1586
|
+
|
|
1587
|
+
function usePreviewController(iframeRef){const[height,setHeight]=React__namespace.useState(null);const[isIframeReady,setIsIframeReady]=React__namespace.useState(false);const pendingDataRef=React__namespace.useRef(null);React__namespace.useEffect(()=>{const handleMessage=event=>{if(iframeRef.current?.contentWindow==null||event.source!==iframeRef.current?.contentWindow){return}const message=event.data;if(!isIframeToParentMessage(message)){return}switch(message.type){case "iframe-ready":{if(pendingDataRef.current){const sanitizedData=sanitizePreviewData(pendingDataRef.current);const msg={source:PREVIEW_MESSAGE_SOURCE,type:"content-data",content:sanitizedData};iframeRef.current.contentWindow.postMessage(msg,"/");pendingDataRef.current=null;}setIsIframeReady(true);break}case "height-update":setHeight(message.height);break;default:throw new wonderStuffCore.UnreachableCaseError(message)}};window.addEventListener("message",handleMessage);return ()=>{window.removeEventListener("message",handleMessage);}},[iframeRef]);const sendData=React__namespace.useCallback(data=>{if(!isIframeReady){pendingDataRef.current=data;return}const contentWindow=iframeRef.current?.contentWindow;if(!contentWindow){return}const sanitizedData=sanitizePreviewData(data);const message={source:PREVIEW_MESSAGE_SOURCE,type:"content-data",content:sanitizedData};contentWindow.postMessage(message,"/");},[iframeRef,isIframeReady]);return {sendData,height}}
|
|
1588
|
+
|
|
1589
|
+
function usePreviewPresenter(){const[data,setData]=React__namespace.useState(null);const iframe=window.frameElement;if(iframe==null){throw new Error("usePreviewPresenter must be used within an iframe")}React__namespace.useEffect(()=>{const handleMessage=event=>{if(event.source!==window.parent){return}const message=event.data;if(!isParentToIframeMessage(message)){return}switch(message.type){case "content-data":setData(message.content);break;default:throw new wonderStuffCore.UnreachableCaseError(message.type)}};window.addEventListener("message",handleMessage);window.parent.postMessage(createPreviewIframeReadyMessage(),"/");return ()=>{window.removeEventListener("message",handleMessage);}},[]);const reportHeight=React__namespace.useCallback(height=>{if(window.parent==null){return}const message={source:PREVIEW_MESSAGE_SOURCE,type:"height-update",height};window.parent.postMessage(message,"/");},[]);return {data,isMobile:iframe.dataset.mobile==="true",hasLintGutter:iframe.dataset.lintGutter==="true",reportHeight}}
|
|
1590
|
+
|
|
1577
1591
|
const{TextListEditor: TextListEditor$4}=perseus.components;const Categorizer=perseus.Categorizer.widget;class CategorizerEditor extends React__namespace.Component{render(){const categorizerProps={items:this.props.items,categories:this.props.categories,userInput:{values:this.props.values},handleUserInput:userInput=>{this.props.onChange({values:userInput.values});},apiOptions:this.props.apiOptions,trackInteraction:function(){}};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(wonderBlocksForm.Checkbox,{label:"Randomize item order",checked:this.props.randomizeItems,onChange:value=>{this.props.onChange({randomizeItems:value});}})}),"Categories:",jsxRuntimeExports.jsx(TextListEditor$4,{options:this.props.categories,onChange:cat=>{this.change("categories",cat);},layout:"horizontal"}),"Items:",jsxRuntimeExports.jsx(TextListEditor$4,{options:this.props.items,onChange:items=>{this.change({items:items,values:___default.default.first(this.props.values,items.length)});},layout:"vertical"}),jsxRuntimeExports.jsx(Categorizer,{...categorizerProps})]})}constructor(...args){super(...args),this.change=(...args)=>{return perseus.Changeable.change.apply(this,args)},this.serialize=()=>{return perseus.EditorJsonify.serialize.call(this)};}}CategorizerEditor.propTypes={...perseus.Changeable.propTypes,apiOptions:perseus.ApiOptions.propTypes,items:PropTypes__default.default.arrayOf(PropTypes__default.default.string),categories:PropTypes__default.default.arrayOf(PropTypes__default.default.string),values:PropTypes__default.default.arrayOf(PropTypes__default.default.number),randomizeItems:PropTypes__default.default.bool};CategorizerEditor.widgetName="categorizer";CategorizerEditor.defaultProps=perseusCore.categorizerLogic.defaultWidgetOptions;
|
|
1578
1592
|
|
|
1579
1593
|
class BlurInput extends React__namespace.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({value:nextProps.value});}focus(){this.input.current?.focus();}render(){return jsxRuntimeExports.jsx("input",{ref:this.input,className:this.props.className,style:this.props.style,type:"text",value:this.state.value,onChange:this.handleChange,onBlur:this.handleBlur})}constructor(props){super(props),this.input=React__namespace.createRef(),this.handleChange=e=>{this.setState({value:e.target.value});},this.handleBlur=e=>{this.props.onChange(e.target.value);};this.state={value:this.props.value};}}
|
|
@@ -1613,7 +1627,7 @@ const wbFieldStyles={root:{marginBlockEnd:wonderBlocksTokens.sizing.size_080},la
|
|
|
1613
1627
|
|
|
1614
1628
|
var styles$I = {"decorativeToggleContainer":"perseus_Z9--Lqsc","flexRow":"perseus_H6OWRNo-"};
|
|
1615
1629
|
|
|
1616
|
-
const{InfoTip: InfoTip$h}=perseus.components;function DecorativeToggle({decorative,hasPopulatedFields,onChange}){function handleDecorativeToggle(newValue){if(!newValue){onChange({decorative:false});return}if(!hasPopulatedFields){onChange({decorative:true});return}const shouldReset=window.confirm("Setting this image as decorative will automatically reset all other fields (title, caption, alt text, and long description). Do you want to continue?");if(shouldReset){onChange({decorative:true,alt:"",caption:undefined,title:undefined,longDescription:undefined});}}return jsxRuntimeExports.jsx("div",{className:styles$I.decorativeToggleContainer,children:jsxRuntimeExports.jsxs("div",{className:styles$I.flexRow,children:[jsxRuntimeExports.jsx(LabeledSwitch
|
|
1630
|
+
const{InfoTip: InfoTip$h}=perseus.components;function DecorativeToggle({decorative,hasPopulatedFields,onChange}){function handleDecorativeToggle(newValue){if(!newValue){onChange({decorative:false});return}if(!hasPopulatedFields){onChange({decorative:true});return}const shouldReset=window.confirm("Setting this image as decorative will automatically reset all other fields (title, caption, alt text, and long description). Do you want to continue?");if(shouldReset){onChange({decorative:true,alt:"",caption:undefined,title:undefined,longDescription:undefined});}}return jsxRuntimeExports.jsx("div",{className:styles$I.decorativeToggleContainer,children:jsxRuntimeExports.jsxs("div",{className:styles$I.flexRow,children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Decorative",checked:decorative??false,onChange:handleDecorativeToggle}),jsxRuntimeExports.jsx(InfoTip$h,{children:jsxRuntimeExports.jsx("p",{children:"Mark this image as decorative and it will not have any alt text, description, title, or caption."})})]})})}
|
|
1617
1631
|
|
|
1618
1632
|
const ScrolllessNumberTextField=props=>{const{value,onChange,...restOfProps}=props;const[focused,setFocused]=React__namespace.useState(false);const[wipValue,setWipValue]=React__namespace.useState("");const inputRef=React__namespace.useRef(null);React__namespace.useEffect(()=>{const ref=inputRef.current;const ignoreScroll=e=>{e.stopPropagation();};ref?.addEventListener("wheel",ignoreScroll);return ()=>{ref?.removeEventListener("wheel",ignoreScroll);}},[inputRef]);return jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{...restOfProps,type:"number",value:focused?wipValue:value,onChange:newValue=>{setWipValue(newValue);onChange(newValue);},onFocus:e=>{setWipValue(value);setFocused(true);props.onFocus?.(e);},onBlur:e=>{setFocused(false);props.onBlur?.(e);},ref:inputRef})};
|
|
1619
1633
|
|
|
@@ -1661,7 +1675,7 @@ const{getDependencies}=perseus.Dependencies;const{unescapeMathMode}=perseus.Util
|
|
|
1661
1675
|
|
|
1662
1676
|
var styles$G = {"singleSelectShort":"perseus_wAZzFxEx","row":"perseus_6FquBkGo"};
|
|
1663
1677
|
|
|
1664
|
-
const LabeledRow=props=>{const{children,label,labelSide="left",style}=props;return jsxRuntimeExports.jsx("label",{className:aphrodite.css(styles$F.label),children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$F.row,style],children:[labelSide==="start"||jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",style:styles$F.spaceEnd,children:label}),children,labelSide==="end"&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",style:styles$F.spaceStart,children:label})]})})};const styles$F=aphrodite.StyleSheet.create({label:{width:"fit-content"},row:{flexDirection:"row",marginTop:wonderBlocksTokens.spacing.xSmall_8,alignItems:"center",width:"fit-content"},spaceStart:{marginInlineStart:wonderBlocksTokens.spacing.xSmall_8},spaceEnd:{marginInlineEnd:wonderBlocksTokens.spacing.xSmall_8}});
|
|
1678
|
+
const LabeledRow=props=>{const{children,label,labelSide="left",labelSize="small",style}=props;return jsxRuntimeExports.jsx("label",{className:aphrodite.css(styles$F.label),children:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$F.row,style],children:[labelSide==="start"||jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:labelSize==="small"?"small":undefined,tag:"span",style:styles$F.spaceEnd,children:label}),children,labelSide==="end"&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:labelSize==="small"?"small":undefined,tag:"span",style:styles$F.spaceStart,children:label})]})})};const styles$F=aphrodite.StyleSheet.create({label:{width:"fit-content"},row:{flexDirection:"row",marginTop:wonderBlocksTokens.spacing.xSmall_8,alignItems:"center",width:"fit-content"},spaceStart:{marginInlineStart:wonderBlocksTokens.spacing.xSmall_8},spaceEnd:{marginInlineEnd:wonderBlocksTokens.spacing.xSmall_8}});
|
|
1665
1679
|
|
|
1666
1680
|
const{InfoTip: InfoTip$f}=perseus.components;function AngleAnswerOptions({correct,graph,onChange}){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:styles$G.row,children:[jsxRuntimeExports.jsx(wonderBlocksForm.Checkbox,{label:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",children:"Show angle measures"}),checked:!!correct?.showAngles,onChange:newValue=>{if(graph?.type==="angle"){invariant__default.default(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);onChange({correct:{...correct,showAngles:newValue},graph:{...graph,showAngles:newValue}});}}}),jsxRuntimeExports.jsx(InfoTip$f,{children:jsxRuntimeExports.jsx("p",{children:"Displays the interior angle measures."})})]}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{className:styles$G.row,children:[jsxRuntimeExports.jsx(wonderBlocksForm.Checkbox,{label:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",tag:"span",children:"Allow reflex angles"}),checked:!!correct?.allowReflexAngles,onChange:newValue=>{invariant__default.default(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);invariant__default.default(graph?.type==="angle",`Expected graph type to be angle, but got ${graph?.type}`);const update={allowReflexAngles:newValue};onChange({correct:{...correct,...update},graph:{...graph,...update}});}}),jsxRuntimeExports.jsx(InfoTip$f,{children:jsxRuntimeExports.jsx("p",{children:"Allow students to be able to create reflex angles."})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Student answer must",children:[jsxRuntimeExports.jsxs(wonderBlocksDropdown.SingleSelect,{selectedValue:correct.match||"exact",onChange:newValue=>{invariant__default.default(correct.type==="angle",`Expected graph type to be angle, but got ${correct.type}`);onChange({correct:{...correct,match:newValue}});},placeholder:"",className:styles$G.singleSelectShort,children:[jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"exact",label:"match exactly"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"congruent",label:"be congruent"})]}),jsxRuntimeExports.jsx(InfoTip$f,{children:jsxRuntimeExports.jsx("p",{children:"Congruency requires only that the angle measures are the same. An exact match implies congruency, but also requires that the angles have the same orientation and that the vertices are in the same position."})})]})]})}
|
|
1667
1681
|
|
|
@@ -1669,7 +1683,7 @@ const UNLIMITED="unlimited";const parsePointCount=points=>{const parsed=parseInt
|
|
|
1669
1683
|
|
|
1670
1684
|
const GraphPointsCountSelector=({correct,graph,onChange})=>{return jsxRuntimeExports.jsx(LabeledRow,{label:"Number of Points:",children:jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{selectedValue:`${correct.numPoints??1}`,onChange:newValue=>{const points=parsePointCount(newValue);onChange({correct:{type:"point",numPoints:points},graph:{type:"point",numPoints:points}});},placeholder:"",className:styles$G.singleSelectShort,children:[...[...Array(7).keys()].map(n=>jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:`${n}`,label:`${n} point${n>1?"s":""}`},n)),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:UNLIMITED,label:"unlimited"},"unlimited")]})})};
|
|
1671
1685
|
|
|
1672
|
-
const GraphTypeSelector=props=>{const
|
|
1686
|
+
const GraphTypeSelector=props=>{const showVector=perseusCore.isFeatureOn({apiOptions:props.apiOptions},"interactive-graph-vector");return jsxRuntimeExports.jsxs(wonderBlocksDropdown.SingleSelect,{selectedValue:props.graphType,onChange:props.onChange,placeholder:"Select an answer type",style:styles$E.singleSelectShort,children:[jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"absolute-value",label:"Absolute value"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"none",label:"None"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"linear",label:"Linear function"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"quadratic",label:"Quadratic function"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"sinusoid",label:"Sinusoid function"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"exponential",label:"Exponential function"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"tangent",label:"Tangent function"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"logarithm",label:"Logarithm function"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"circle",label:"Circle"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"point",label:"Point(s)"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"linear-system",label:"Linear System"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"polygon",label:"Polygon"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"segment",label:"Line Segment(s)"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"ray",label:"Ray"}),showVector&&jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"vector",label:"Vector"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"angle",label:"Angle"})]})};const styles$E=aphrodite.StyleSheet.create({singleSelectShort:{height:wonderBlocksTokens.sizing.size_260}});
|
|
1673
1687
|
|
|
1674
1688
|
function Heading({title,isOpen,isCollapsible,onToggle}){return jsxRuntimeExports.jsx(Clickable__default.default,{style:[styles$D.container,!isCollapsible&&styles$D.notClickable],disabled:!isCollapsible,onClick:()=>isCollapsible&&onToggle?.(!isOpen),children:()=>jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$D.heading,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",weight:"bold",tag:"span",children:title}),isCollapsible&&jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:isOpen})]})})}const styles$D=aphrodite.StyleSheet.create({container:{marginTop:wonderBlocksTokens.spacing.small_12,marginInline:-10,backgroundColor:wonderBlocksTokens.semanticColor.core.background.neutral.subtle,padding:wonderBlocksTokens.spacing.xSmall_8,width:"calc(100% + 20px)"},heading:{flexDirection:"row",justifyContent:"space-between",userSelect:"none"},notClickable:{color:"inherit",cursor:"default"}});
|
|
1675
1689
|
|
|
@@ -1677,7 +1691,7 @@ function InteractiveGraphCorrectAnswer(props){return jsxRuntimeExports.jsxs(jsxR
|
|
|
1677
1691
|
|
|
1678
1692
|
function InteractiveGraphDescription(props){const{ariaLabelValue,ariaDescriptionValue,onChange}=props;const[isOpen,setIsOpen]=React__namespace.useState(true);const uniqueId=React__namespace.useId();const descriptionTextAreaId=`${uniqueId}-description-textarea`;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Description",isCollapsible:true,isOpen:isOpen,onToggle:setIsOpen}),isOpen&&jsxRuntimeExports.jsxs(wonderBlocksCore.View,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"xsmall",style:styles$C.caption,children:"Use these fields to describe the graph as a whole. These are used by screen readers to describe content to users who may be visually impaired."}),jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"label",children:["Title",jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{value:ariaLabelValue,onChange:newValue=>onChange({fullGraphAriaLabel:newValue||undefined}),style:styles$C.spaceAbove})]}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"label",htmlFor:descriptionTextAreaId,children:"Description"}),jsxRuntimeExports.jsx(wonderBlocksForm.TextArea,{id:descriptionTextAreaId,value:ariaDescriptionValue,onChange:newValue=>onChange({fullGraphAriaDescription:newValue||undefined}),autoResize:true})]})]})}const styles$C=aphrodite.StyleSheet.create({caption:{color:wonderBlocksTokens.semanticColor.core.foreground.neutral.subtle,paddingTop:wonderBlocksTokens.spacing.xxSmall_6,paddingBottom:wonderBlocksTokens.spacing.xxSmall_6},spaceAbove:{marginTop:wonderBlocksTokens.spacing.xxxSmall_4}});
|
|
1679
1693
|
|
|
1680
|
-
function AxisArrowSwitches(props){const{showAxisArrows,onChange,disabled}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",children:"Arrows"}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",style:{display:"flex",flexDirection:"row",alignItems:"center",gap:wonderBlocksTokens.sizing.size_060},children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledSwitch
|
|
1694
|
+
function AxisArrowSwitches(props){const{showAxisArrows,onChange,disabled}=props;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",children:"Arrows"}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",style:{display:"flex",flexDirection:"row",alignItems:"center",gap:wonderBlocksTokens.sizing.size_060},children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"x min",labelSide:"start",size:"small",checked:showAxisArrows.xMin,disabled:disabled,onChange:()=>onChange("xMin")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"y min",labelSide:"start",size:"small",checked:showAxisArrows.yMin,disabled:disabled,onChange:()=>onChange("yMin")})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",style:{display:"flex",flexDirection:"row",alignItems:"center",gap:wonderBlocksTokens.sizing.size_060},children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"x max",labelSide:"start",size:"small",checked:showAxisArrows.xMax,disabled:disabled,onChange:()=>onChange("xMax")})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledSwitch,{label:"y max",labelSide:"start",size:"small",checked:showAxisArrows.yMax,disabled:disabled,onChange:()=>onChange("yMax")})})]})]})}
|
|
1681
1695
|
|
|
1682
1696
|
const{ButtonGroup: ButtonGroup$1,InfoTip: InfoTip$e,RangeInput: RangeInput$4}=perseus.components;const defaultBackgroundImage={url:null,width:0,height:0};function numSteps(range,step){return Math.floor((range[1]-range[0])/step)}class InteractiveGraphSettings extends React__namespace.Component{static stateFromProps(props){return {labelsTextbox:props.labels,labelLocation:props.labelLocation,gridStepTextbox:props.gridStep,snapStepTextbox:props.snapStep,stepTextbox:props.step,rangeTextbox:props.range,showAxisArrowsSwitches:props.showAxisArrows,backgroundImage:{...props.backgroundImage}}}componentDidMount(){this._isMounted=true;this.changeGraph=___default.default.debounce(this.changeGraph,300);}UNSAFE_componentWillReceiveProps(nextProps){if(!___default.default.isEqual(this.props.labels,nextProps.labels)||!___default.default.isEqual(this.props.labelLocation,nextProps.labelLocation)||!___default.default.isEqual(this.props.gridStep,nextProps.gridStep)||!___default.default.isEqual(this.props.snapStep,nextProps.snapStep)||!___default.default.isEqual(this.props.step,nextProps.step)||!___default.default.isEqual(this.props.range,nextProps.range)||!___default.default.isEqual(this.props.backgroundImage,nextProps.backgroundImage)){this.setState(InteractiveGraphSettings.stateFromProps(nextProps));}}componentWillUnmount(){this._isMounted=false;}render(){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Heading,{title:"Common Graph Settings",isOpen:this.state.isExpanded,isCollapsible:true,onToggle:()=>this.setState({isExpanded:!this.state.isExpanded})}),this.state.isExpanded&&jsxRuntimeExports.jsxs(wonderBlocksCore.View,{children:[jsxRuntimeExports.jsxs("div",{className:"graph-settings",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Label Location",children:jsxRuntimeExports.jsx(ButtonGroup$1,{value:this.props.labelLocation,allowEmpty:false,buttons:[{value:"onAxis",content:"On Axis"},{value:"alongEdge",content:"Along Graph Edge"}],onChange:this.change("labelLocation")})})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"x Label",children:jsxRuntimeExports.jsx("input",{type:"text",className:"graph-settings-axis-label",ref:this.labelXRef,onChange:e=>this.changeLabel(0,e),value:this.state.labelsTextbox[0]||""})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"y Label",children:jsxRuntimeExports.jsx("input",{type:"text",className:"graph-settings-axis-label",ref:this.labelYRef,onChange:e=>this.changeLabel(1,e),value:this.state.labelsTextbox[1]||""})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"x Range",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.rangeTextbox[0],onChange:vals=>this.changeRange(0,vals),allowPiTruncation:true})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"y Range",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.rangeTextbox[1],onChange:vals=>this.changeRange(1,vals),allowPiTruncation:true})})})]}),jsxRuntimeExports.jsx(AxisArrowSwitches,{showAxisArrows:this.state.showAxisArrowsSwitches,onChange:this.changeShowAxisArrows,disabled:this.props.apiOptions?.editingDisabled??false}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Tick Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.stepTextbox,onChange:this.changeStep,allowPiTruncation:true})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-right-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Grid Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.gridStepTextbox,onChange:this.changeGridStep,allowPiTruncation:true})})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Snap Step",children:jsxRuntimeExports.jsx(RangeInput$4,{value:this.state.snapStepTextbox,onChange:this.changeSnapStep,allowPiTruncation:true})})}),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-right-col",children:[jsxRuntimeExports.jsx(Button__default.default,{size:"small",kind:"tertiary",onClick:()=>{this.changeStepsBasedOnRange();},children:"Auto-adjust steps"}),jsxRuntimeExports.jsxs(InfoTip$e,{children:[jsxRuntimeExports.jsx("p",{children:'Use the "Auto-adjust" steps button to update the tick step, grid step, and snap step to values that are valid for the current range.'}),jsxRuntimeExports.jsx("br",{}),jsxRuntimeExports.jsx("p",{children:"This is useful when the range is changed, and the graph errors due to the step sizes being too large or too small."})]})]})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-row",children:jsxRuntimeExports.jsx(LabeledRow,{label:"Markings:",children:jsxRuntimeExports.jsx(ButtonGroup$1,{value:this.props.markings,allowEmpty:false,buttons:[{value:"axes",content:"Axes"},{value:"graph",content:"Graph"},{value:"grid",content:"Grid"},{value:"none",content:"None"}],onChange:this.change("markings")})})}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-left-col",children:jsxRuntimeExports.jsx(wonderBlocksForm.Checkbox,{label:"Show tooltips",checked:this.props.showTooltips,onChange:value=>{this.change({showTooltips:value});}})})]}),jsxRuntimeExports.jsxs(LabeledRow,{label:"Background image URL:",style:styles$B.resetSpaceTop,children:[jsxRuntimeExports.jsx("input",{type:"text",className:aphrodite.css(styles$B.backgroundUrlInput),ref:this.bgUrlRef,value:this.state.backgroundImage.url||"",onChange:e=>{const image={...this.props.backgroundImage};image.url=e.target.value;this.setState({backgroundImage:image});},onKeyPress:this.changeBackgroundUrl,onBlur:this.changeBackgroundUrl}),jsxRuntimeExports.jsx(InfoTip$e,{children:jsxRuntimeExports.jsx("p",{children:'Create an image in graphie, or use the "Add image" function to create a background.'})})]}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$B.protractorSection,children:[jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$B.checkboxRow,children:jsxRuntimeExports.jsx(wonderBlocksForm.Checkbox,{label:"Show protractor",checked:this.props.showProtractor,onChange:value=>{this.change({showProtractor:value});},style:styles$B.resetSpaceTop})}),this.props.showProtractor&&jsxRuntimeExports.jsx(Banner__default.default,{text:"The protractor is not accessible. Please consider an alternate approach.",kind:"warning"})]})]})]})}constructor(props){super(props),this._isMounted=false,this.bgUrlRef=React__namespace.createRef(),this.labelXRef=React__namespace.createRef(),this.labelYRef=React__namespace.createRef(),this.change=(...args)=>{return perseus.Changeable.change.apply(this,args)},this.changeBackgroundUrl=e=>{if(e.type==="keypress"&&e.key!=="Enter"){return}const setUrl=(url,width,height)=>{const image={...this.props.backgroundImage};image.url=url;image.width=width;image.height=height;this.setState({backgroundImage:image},this.changeGraph);};const url=this.bgUrlRef.current?.value;if(url){perseus.Util.getImageSize(url,(width,height)=>{if(this._isMounted){setUrl(url,width,height);}});}else {setUrl(null,0,0);}},this.renderLabelChoices=choices=>{return choices.map(nameAndValue=>jsxRuntimeExports.jsx("option",{value:nameAndValue[1],children:nameAndValue[0]},nameAndValue[1]))},this.validRange=range=>{const numbers=___default.default.every(range,function(num){return ___default.default.isFinite(num)});if(!numbers){return "Range must be a valid number"}if(range[0]>=range[1]){return "Range must have a higher number on the right"}return true},this.validateStepValue=settings=>{const{step,range,name,minTicks,maxTicks}=settings;const nSteps=numSteps(range,step);if(nSteps<minTicks){return name+" is too large, there must be at least "+minTicks+" ticks."}if(nSteps>maxTicks){return name+" is too small, there can be at most "+maxTicks+" ticks."}return true},this.validSnapStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Snap step",minTicks:5,maxTicks:60})},this.validGridStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Grid step",minTicks:3,maxTicks:60})},this.validStep=(step,range)=>{return this.validateStepValue({step:step,range:range,name:"Step",minTicks:3,maxTicks:20})},this.validBackgroundImageSize=image=>{if(!image.url){return true}const validSize=image.width<=450&&image.height<=450;if(!validSize){return "Image must be smaller than 450px x 450px."}return true},this.validateGraphSettings=(range,step,gridStep,snapStep,image)=>{const self=this;let msg;const goodRange=___default.default.every(range,function(range){msg=self.validRange(range);return msg===true});if(!goodRange){return msg}const goodStep=___default.default.every(step,function(step,i){msg=self.validStep(step,range[i]);return msg===true});if(!goodStep){return msg}const goodGridStep=___default.default.every(gridStep,function(gridStep,i){msg=self.validGridStep(gridStep,range[i]);return msg===true});if(!goodGridStep){return msg}const goodSnapStep=___default.default.every(snapStep,function(snapStep,i){msg=self.validSnapStep(snapStep,range[i]);return msg===true});if(!goodSnapStep){return msg}const goodImageSize=this.validBackgroundImageSize(image);if(goodImageSize!==true){msg=goodImageSize;return msg}return true},this.changeLabel=(i,e)=>{const val=e.target.value;const labels=this.state.labelsTextbox.slice();labels[i]=val;this.setState({labelsTextbox:labels},this.changeGraph);},this.changeRange=(i,values)=>{const ranges=this.state.rangeTextbox.slice();ranges[i]=values;this.setState({rangeTextbox:ranges},this.changeGraph);},this.changeShowAxisArrows=axis=>{const newShowAxisArrows={...this.state.showAxisArrowsSwitches};newShowAxisArrows[axis]=!newShowAxisArrows[axis];this.setState({showAxisArrowsSwitches:newShowAxisArrows},this.changeGraph);},this.changeStepsBasedOnRange=()=>{const ranges=this.state.rangeTextbox.slice();const step=this.state.stepTextbox.slice();const gridStep=this.state.gridStepTextbox.slice();const snapStep=this.state.snapStepTextbox.slice();const scaleX=perseus.Util.scaleFromExtent(ranges[0],this.props.box[0]);if(this.validRange(ranges[0])===true){step[0]=perseus.Util.tickStepFromExtent(ranges[0],this.props.box[0]);const gridStepValue=perseus.Util.gridStepFromTickStep(step[0],scaleX);if(gridStepValue){gridStep[0]=gridStepValue;}snapStep[0]=gridStep[0]/2;}const scaleY=perseus.Util.scaleFromExtent(ranges[1],this.props.box[1]);if(this.validRange(ranges[1])===true){step[1]=perseus.Util.tickStepFromExtent(ranges[1],this.props.box[1]);const gridStepValue=perseus.Util.gridStepFromTickStep(step[1],scaleY);if(gridStepValue){gridStep[1]=gridStepValue;}snapStep[1]=gridStep[1]/2;}this.setState({stepTextbox:step,gridStepTextbox:gridStep,snapStepTextbox:snapStep,rangeTextbox:ranges},this.changeGraph);},this.changeStep=step=>{this.setState({stepTextbox:step},this.changeGraph);},this.changeSnapStep=snapStep=>{this.setState({snapStepTextbox:snapStep},this.changeGraph);},this.changeGridStep=gridStep=>{this.setState({gridStepTextbox:gridStep,snapStepTextbox:___default.default.map(gridStep,function(step){return step/2})},this.changeGraph);},this.changeGraph=()=>{const labels=this.state.labelsTextbox;const labelLocation=this.state.labelLocation;const range=this.state.rangeTextbox.map(range=>range.map(value=>Number(value)));const showAxisArrows=this.state.showAxisArrowsSwitches;const step=this.state.stepTextbox.map(value=>Number(value));const gridStep=this.state.gridStepTextbox;const snapStep=this.state.snapStepTextbox;const image=this.state.backgroundImage;const validationResult=this.validateGraphSettings(range,step,gridStep,snapStep,image);if(validationResult===true){this.change({valid:true,labels:labels,labelLocation:labelLocation,range:range,showAxisArrows:showAxisArrows,step:step,gridStep:gridStep,snapStep:snapStep,backgroundImage:image});}else {this.change({valid:validationResult});}};this.state={isExpanded:true,...InteractiveGraphSettings.stateFromProps(props)};}}InteractiveGraphSettings.defaultProps={box:[perseus.interactiveSizes.defaultBoxSizeSmall,perseus.interactiveSizes.defaultBoxSizeSmall],labels:["$x$","$y$"],labelLocation:"onAxis",range:[[-10,10],[-10,10]],step:[1,1],gridStep:[1,1],snapStep:[1,1],valid:true,backgroundImage:defaultBackgroundImage,markings:"graph",showProtractor:false,showTooltips:false,showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true}};const styles$B=aphrodite.StyleSheet.create({resetSpaceTop:{marginTop:0},backgroundUrlInput:{border:`1px solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderRadius:wonderBlocksTokens.spacing.xxxSmall_4,padding:wonderBlocksTokens.spacing.xxxSmall_4},checkboxRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:wonderBlocksTokens.spacing.xSmall_8},protractorSection:{marginTop:wonderBlocksTokens.spacing.xSmall_8,borderTop:`1px solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,paddingTop:wonderBlocksTokens.spacing.xSmall_8,paddingBottom:wonderBlocksTokens.spacing.xSmall_8,borderBottom:`1px solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`}});
|
|
1683
1697
|
|
|
@@ -1721,14 +1735,14 @@ const examples={linear:["x + 5","1/2x - 2"],polynomial:["1/2x^2 + 3x - 4","(1/3)
|
|
|
1721
1735
|
|
|
1722
1736
|
const LockedFunctionSettings=props=>{const{color:lineColor,strokeStyle,equation,directionalAxis,domain,weight,ariaLabel,onChangeProps,onMove,onRemove}=props;const labels=props.labels;const equationPrefix=directionalAxis==="x"?"y=":"x=";const lineLabel=`Function (${equationPrefix}${equation})`;const getDomainStringValues=domain=>{return [Number.isFinite(domain[0])?domain[0].toString():"",Number.isFinite(domain[1])?domain[1].toString():""]};const[domainEntries,setDomainEntries]=React.useState(getDomainStringValues(domain));const[exampleCategory,setExampleCategory]=React.useState("");React.useEffect(()=>{setDomainEntries(getDomainStringValues(domain));},[domain]);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Function${visiblelabel} with equation ${equationPrefix}${equation}`;if(Number.isFinite(domain[0])||Number.isFinite(domain[1])){str+=`, domain from ${domain[0]} to ${domain[1]}`;}const functionAppearance=generateLockedFigureAppearanceDescription(lineColor,strokeStyle,undefined,weight);str+=functionAppearance;return str}function handlePropChange(property,newValue){const updatedProps={};updatedProps[property]=newValue;onChangeProps(updatedProps);}function handleDomainChange(limitIndex,newValueString){const newDomainEntries=[...domainEntries];newDomainEntries[limitIndex]=newValueString;setDomainEntries(newDomainEntries);const newDomain=[...domain];let newValue=parseFloat(newValueString);if(newValueString===""&&limitIndex===0){newValue=-Infinity;}else if(newValueString===""&&limitIndex===1){newValue=Infinity;}newDomain[limitIndex]=newValue;onChangeProps({domain:newDomain});}const exampleCategories=Object.keys(examples);const exampleCategorySelected=exampleCategory!=="";const exampleContent=exampleCategorySelected?examples[exampleCategory]:["Select category to see example equations"];function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$n.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",style:styles$n.accordionHeader,children:lineLabel}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$n.row,{marginBottom:wonderBlocksTokens.sizing.size_080}],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:newValue=>{handlePropChange("strokeStyle",newValue);}})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$n.row,styles$n.rowSpace],children:[jsxRuntimeExports.jsxs(wonderBlocksDropdown.SingleSelect,{selectedValue:directionalAxis,onChange:newValue=>{handlePropChange("directionalAxis",newValue);},"aria-label":"equation prefix",style:[styles$n.dropdownLabel,styles$n.axisMenu],placeholder:"",children:[jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"x",label:"y ="}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"y",label:"x ="})]}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{type:"text","aria-label":"equation",value:equation,onChange:newValue=>{handlePropChange("equation",newValue);},style:[styles$n.textField]})]}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$n.row,styles$n.rowSpace],children:[jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{tag:"label",style:[styles$n.dropdownLabel,styles$n.domainMin],children:["domain min",jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxSmall_6}),jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{type:"number",style:styles$n.domainMinField,value:domainEntries[0],onChange:newValue=>{handleDomainChange(0,newValue);}})]}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.medium_16}),jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{tag:"label","aria-label":"domain max",style:[styles$n.dropdownLabel,styles$n.domainMax],children:["max",jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxSmall_6}),jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{type:"number",style:styles$n.domainMaxField,value:domainEntries[1],onChange:newValue=>{handleDomainChange(1,newValue);}})]})]}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:"Example Functions"}),expanded:false,containerStyle:styles$n.exampleWorkspace,panelStyle:styles$n.exampleAccordionPanel,children:[jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{tag:"label",style:styles$n.dropdownLabel,children:["Choose a category",jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxSmall_6}),jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{selectedValue:exampleCategory,onChange:setExampleCategory,placeholder:"examples",children:exampleCategories.map(category=>{return jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:category,label:category},category)})})]}),exampleCategorySelected&&jsxRuntimeExports.jsx("ul",{className:aphrodite.css(styles$n.exampleContainer),children:exampleContent.map((example,index)=>jsxRuntimeExports.jsx(ExampleItem,{category:exampleCategory,example:example,index:index,pasteEquationFn:handlePropChange},index))})]}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$n.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$n.horizontalRule}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{children:"Visible labels"}),labels.map((label,labelIndex)=>jsxRuntimeExports.jsx(LockedLabelSettings,{...label,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$n.labelContainer},labelIndex)),jsxRuntimeExports.jsx(Button__default.default,{kind:"tertiary",startIcon:plusCircle__default.default,onClick:()=>{const newLabel={...perseusCore.getDefaultFigureForType("label"),coord:[0,-labels.length],color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$n.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const ExampleItem=props=>{const{category,example,index,pasteEquationFn}=props;const exampleId=React.useId();return jsxRuntimeExports.jsxs("li",{className:aphrodite.css(styles$n.exampleRow),children:[jsxRuntimeExports.jsx(IconButton__default.default,{icon:autoPasteIcon__default.default,kind:"tertiary","aria-label":"paste example","aria-describedby":exampleId,onClick:()=>pasteEquationFn("equation",example),size:"medium",style:styles$n.copyPasteButton}),jsxRuntimeExports.jsx(IconButton__default.default,{icon:copyIcon__default.default,kind:"tertiary","aria-label":"copy example","aria-describedby":exampleId,onClick:()=>navigator.clipboard.writeText(example),size:"medium",style:styles$n.copyPasteButton}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$n.exampleContent,id:exampleId,children:example})]},`${category}-${index}`)};const styles$n=aphrodite.StyleSheet.create({accordionHeader:{textOverflow:"ellipsis",maxWidth:"calc(100% - 64px)",overflow:"hidden",whiteSpace:"nowrap"},axisMenu:{minWidth:"auto"},copyPasteButton:{flexShrink:"0",margin:"0 2px"},domainMin:{justifyContent:"space-between",width:"calc(((100% - 141px) / 2) + 88.7px)",textWrap:"nowrap"},domainMinField:{width:"calc(100% - 88.7px)"},domainMax:{width:"calc(((100% - 141px) / 2) + 36.2px)"},domainMaxField:{width:"calc(100% - 36.2px)"},dropdownLabel:{alignItems:"center",display:"flex"},exampleAccordionPanel:{alignItems:"start",paddingBottom:"12px",flexDirection:"row",flexWrap:"wrap"},exampleContainer:{background:"white",border:`1px solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderRadius:"4px",flexGrow:"1",listStyleType:"none",maxHeight:"88px",margin:"8px 0 0 0",overflowY:"scroll",padding:"4px 12px 4px 4px"},exampleContent:{fontFamily:`"Lato", sans-serif`,flexGrow:"1",color:wonderBlocksTokens.semanticColor.core.foreground.neutral.strong},exampleRow:{alignItems:"center",display:"flex",flexDirection:"row",minHeight:"44px"},exampleWorkspace:{background:wonderBlocksTokens.semanticColor.core.background.base.subtle},rowSpace:{marginTop:wonderBlocksTokens.spacing.xSmall_8},row:{display:"flex",flexDirection:"row",alignItems:"center"},textField:{flexGrow:"1"},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle},labelContainer:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default}});
|
|
1723
1737
|
|
|
1724
|
-
const LockedPointSettings=props=>{const{headerLabel,coord,color:pointColor,filled=true,labels,ariaLabel,onChangeProps,onMove,onRemove,showPoint,error,expanded,onTogglePoint,onToggle}=props;const isDefiningPoint=!onMove&&!onRemove;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenX=await generateSpokenMathDetails(`$${coord[0]}$`);const spokenY=await generateSpokenMathDetails(`$${coord[1]}$`);let str=`Point${visiblelabel} at ${spokenX} comma ${spokenY}`;const pointAppearance=generateLockedFigureAppearanceDescription(pointColor,"solid",filled?undefined:"none");str+=pointAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleCoordChange(newCoord){const xOffset=newCoord[0]-coord[0];const yOffset=newCoord[1]-coord[1];const newProps={coord:newCoord};newProps.labels=labels.map(label=>({...label,coord:[label.coord[0]+xOffset,label.coord[1]+yOffset]}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,containerStyle:isDefiningPoint?styles$m.definingContainer:undefined,panelStyle:isDefiningPoint?styles$m.definingPanel:undefined,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$m.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:`${headerLabel||"Point"} (${coord[0]}, ${coord[1]})`}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(ColorSwatch,{color:pointColor,filled:filled})]}),children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,style:styles$m.spaceUnder,onChange:handleCoordChange,error:!!error}),onTogglePoint&&jsxRuntimeExports.jsx(LabeledSwitch
|
|
1738
|
+
const LockedPointSettings=props=>{const{headerLabel,coord,color:pointColor,filled=true,labels,ariaLabel,onChangeProps,onMove,onRemove,showPoint,error,expanded,onTogglePoint,onToggle}=props;const isDefiningPoint=!onMove&&!onRemove;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenX=await generateSpokenMathDetails(`$${coord[0]}$`);const spokenY=await generateSpokenMathDetails(`$${coord[1]}$`);let str=`Point${visiblelabel} at ${spokenX} comma ${spokenY}`;const pointAppearance=generateLockedFigureAppearanceDescription(pointColor,"solid",filled?undefined:"none");str+=pointAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handleCoordChange(newCoord){const xOffset=newCoord[0]-coord[0];const yOffset=newCoord[1]-coord[1];const newProps={coord:newCoord};newProps.labels=labels.map(label=>({...label,coord:[label.coord[0]+xOffset,label.coord[1]+yOffset]}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,containerStyle:isDefiningPoint?styles$m.definingContainer:undefined,panelStyle:isDefiningPoint?styles$m.definingPanel:undefined,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$m.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:`${headerLabel||"Point"} (${coord[0]}, ${coord[1]})`}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(ColorSwatch,{color:pointColor,filled:filled})]}),children:[jsxRuntimeExports.jsx(CoordinatePairInput,{coord:coord,style:styles$m.spaceUnder,onChange:handleCoordChange,error:!!error}),onTogglePoint&&jsxRuntimeExports.jsx(LabeledSwitch,{label:"show point on graph",checked:!!showPoint,style:showPoint&&styles$m.spaceUnder,onChange:onTogglePoint}),(!isDefiningPoint||showPoint)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:pointColor,onChange:handleColorChange,style:styles$m.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"open point",checked:!filled,onChange:newValue=>{onChangeProps({filled:!newValue});}})]}),!isDefiningPoint&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$m.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}})]}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$m.horizontalRule}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{children:"Visible labels"}),labels.map((label,labelIndex)=>React.createElement(LockedLabelSettings,{...label,key:labelIndex,containerStyle:!isDefiningPoint&&styles$m.lockedPointLabelContainer,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);}})),jsxRuntimeExports.jsx(Button__default.default,{kind:"tertiary",startIcon:plusCircle__default.default,onClick:()=>{const newLabel={...perseusCore.getDefaultFigureForType("label"),coord:[coord[0]+.5,coord[1]-labels.length],color:pointColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$m.addButton,children:"Add visible label"}),onRemove&&jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$m=aphrodite.StyleSheet.create({definingContainer:{marginTop:wonderBlocksTokens.spacing.xSmall_8,marginBottom:0,marginLeft:-wonderBlocksTokens.spacing.xxxSmall_4,marginRight:-wonderBlocksTokens.spacing.xxxSmall_4,backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default},definingPanel:{paddingBottom:wonderBlocksTokens.spacing.xxSmall_6},lockedPointLabelContainer:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default},row:{flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:wonderBlocksTokens.spacing.xSmall_8},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle}});
|
|
1725
1739
|
|
|
1726
1740
|
const lengthZeroStr="The line cannot have length 0.";const LockedLineSettings=props=>{const{kind,points,color:lineColor,lineStyle="solid",showPoint1,showPoint2,weight,labels,ariaLabel,onChangeProps,onMove,onRemove}=props;const[point1,point2]=points;const capitalizeKind=kind.charAt(0).toUpperCase()+kind.slice(1);const lineLabel=`${capitalizeKind} (${point1.coord[0]},
|
|
1727
1741
|
${point1.coord[1]}), (${point2.coord[0]}, ${point2.coord[1]})`;const isInvalid=kmath.vector.equal(point1.coord,point2.coord);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const point1VisibleLabel=await joinLabelsAsSpokenMath(point1.labels);const point2VisibleLabel=await joinLabelsAsSpokenMath(point2.labels);const spokenPoint1X=await generateSpokenMathDetails(`$${point1.coord[0]}$`);const spokenPoint1Y=await generateSpokenMathDetails(`$${point1.coord[1]}$`);const spokenPoint2X=await generateSpokenMathDetails(`$${point2.coord[0]}$`);const spokenPoint2Y=await generateSpokenMathDetails(`$${point2.coord[1]}$`);let str;switch(kind){case "line":str=`${capitalizeKind}${visiblelabel} through point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} and point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;case "ray":str=`${capitalizeKind}${visiblelabel} from point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} through point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;case "segment":str=`${capitalizeKind}${visiblelabel} from point${point1VisibleLabel} at ${spokenPoint1X} comma ${spokenPoint1Y} to point${point2VisibleLabel} at ${spokenPoint2X} comma ${spokenPoint2Y}`;break;default:throw new wonderStuffCore.UnreachableCaseError(kind,"Unknown line kind")}const lineAppearance=generateLockedFigureAppearanceDescription(lineColor,lineStyle,undefined,weight);str+=lineAppearance;return str}function handleChangePoint(newPointProps,index){const newPoints=[...points];newPoints[index]={...points[index],...newPointProps};const oldMidpoint=mafs.vec.midpoint(points[0].coord,points[1].coord);const newMidpoint=mafs.vec.midpoint(newPoints[0].coord,newPoints[1].coord);const offset=[newMidpoint[0]-oldMidpoint[0],newMidpoint[1]-oldMidpoint[1]];const newLabels=labels.map((label,labelIndex)=>({...label,coord:[label.coord[0]+offset[0],label.coord[1]+offset[1]]}));onChangeProps({points:newPoints,labels:newLabels});}function handleColorChange(newColor){const newLabels=labels.map(label=>({...label,color:newColor}));onChangeProps({color:newColor,points:[{...point1,color:newColor,labels:point1.labels.map(label=>({...label,color:newColor}))},{...point2,color:newColor,labels:point2.labels.map(label=>({...label,color:newColor}))}],labels:newLabels});}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$l.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:lineLabel}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:lineStyle})]}),children:[jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{tag:"label",style:[styles$l.row,styles$l.spaceUnder],children:["kind",jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsxs(wonderBlocksDropdown.SingleSelect,{selectedValue:kind,onChange:value=>onChangeProps({kind:value}),placeholder:"",children:[jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"line",label:"line"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"ray",label:"ray"}),jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"segment",label:"segment"})]})]}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$l.row,styles$l.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:lineStyle,onChange:value=>onChangeProps({lineStyle:value})})]}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{style:styles$l.errorText,children:lengthZeroStr}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 1",expanded:true,showPoint:showPoint1,error:isInvalid?lengthZeroStr:null,...point1,onTogglePoint:newValue=>onChangeProps({showPoint1:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,0)}),jsxRuntimeExports.jsx(LockedPointSettings,{headerLabel:"Point 2",expanded:true,showPoint:showPoint2,error:isInvalid?lengthZeroStr:null,...point2,onTogglePoint:newValue=>onChangeProps({showPoint2:newValue}),onChangeProps:newProps=>handleChangePoint(newProps,1)}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$l.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$l.horizontalRule}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{children:"Visible labels"}),labels.map((label,labelIndex)=>React.createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$l.labelContainer})),jsxRuntimeExports.jsx(Button__default.default,{kind:"tertiary",startIcon:plusCircle__default.default,onClick:()=>{const offsetPerLabel=[0,-1];const labelLocation=mafs.vec.add(mafs.vec.scale(offsetPerLabel,labels.length),mafs.vec.midpoint(points[0].coord,points[1].coord));const newLabel={...perseusCore.getDefaultFigureForType("label"),coord:labelLocation,color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$l.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$l=aphrodite.StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},spaceUnder:{marginBottom:wonderBlocksTokens.spacing.xSmall_8},errorText:{color:wonderBlocksTokens.semanticColor.core.foreground.critical.default},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle},labelContainer:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default}});
|
|
1728
1742
|
|
|
1729
1743
|
const PolygonSwatch=props=>{const{color,fillStyle,strokeStyle}=props;return jsxRuntimeExports.jsx(wonderBlocksCore.View,{"aria-label":`${color}, stroke ${strokeStyle}, fill ${fillStyle}`,style:[styles$k.container,{border:`4px ${strokeStyle} ${perseusCore.lockedFigureColors[color]}`}],children:jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:[styles$k.innerSquare,{backgroundColor:perseusCore.lockedFigureColors[color],opacity:fillStyle==="white"?0:perseusCore.lockedFigureFillStyles[fillStyle]}]})})};const styles$k=aphrodite.StyleSheet.create({container:{outline:`2px solid ${wonderBlocksTokens.semanticColor.focus.inner}`,width:wonderBlocksTokens.spacing.large_24,height:wonderBlocksTokens.spacing.large_24,backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default,alignItems:"center",justifyContent:"center"},innerSquare:{width:20,height:20}});
|
|
1730
1744
|
|
|
1731
|
-
const LockedPolygonSettings=props=>{const{points,color,showVertices,fillStyle,strokeStyle,weight,labels,ariaLabel,expanded,onToggle,onChangeProps,onMove,onRemove}=props;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Polygon${visiblelabel} with ${points.length} sides, vertices at `;const pointsList=await Promise.all(points.map(async([x,y])=>{const spokenX=await generateSpokenMathDetails(`$${x}$`);const spokenY=await generateSpokenMathDetails(`$${y}$`);return `${spokenX} comma ${spokenY}`}));str+=pointsList.join(", ");const polygonAppearance=generateLockedFigureAppearanceDescription(color,strokeStyle,fillStyle,weight);str+=polygonAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handlePolygonMove(movement){switch(movement){case "up":onChangeProps({points:points.map(([x,y])=>[x,y+1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]+1]}))});break;case "down":onChangeProps({points:points.map(([x,y])=>[x,y-1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]-1]}))});break;case "left":onChangeProps({points:points.map(([x,y])=>[x-1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]-1,label.coord[1]]}))});break;case "right":onChangeProps({points:points.map(([x,y])=>[x+1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]+1,label.coord[1]]}))});break}}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$j.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:`Polygon, ${points.length} sides`}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(PolygonSwatch,{color:color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$j.row,styles$j.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,onChange:handleColorChange}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.medium_16}),jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{tag:"label",style:[styles$j.row,styles$j.truncatedWidth],children:["fill",jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxSmall_6}),jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{selectedValue:fillStyle,onChange:value=>onChangeProps({fillStyle:value}),placeholder:"",children:Object.keys(perseusCore.lockedFigureFillStyles).map(option=>jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:option,label:option},option))})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:styles$j.spaceUnder}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value}),containerStyle:styles$j.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch
|
|
1745
|
+
const LockedPolygonSettings=props=>{const{points,color,showVertices,fillStyle,strokeStyle,weight,labels,ariaLabel,expanded,onToggle,onChangeProps,onMove,onRemove}=props;async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);let str=`Polygon${visiblelabel} with ${points.length} sides, vertices at `;const pointsList=await Promise.all(points.map(async([x,y])=>{const spokenX=await generateSpokenMathDetails(`$${x}$`);const spokenY=await generateSpokenMathDetails(`$${y}$`);return `${spokenX} comma ${spokenY}`}));str+=pointsList.join(", ");const polygonAppearance=generateLockedFigureAppearanceDescription(color,strokeStyle,fillStyle,weight);str+=polygonAppearance;return str}function handleColorChange(newValue){const newProps={color:newValue};newProps.labels=labels.map(label=>({...label,color:newValue}));onChangeProps(newProps);}function handlePolygonMove(movement){switch(movement){case "up":onChangeProps({points:points.map(([x,y])=>[x,y+1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]+1]}))});break;case "down":onChangeProps({points:points.map(([x,y])=>[x,y-1]),labels:labels.map(label=>({...label,coord:[label.coord[0],label.coord[1]-1]}))});break;case "left":onChangeProps({points:points.map(([x,y])=>[x-1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]-1,label.coord[1]]}))});break;case "right":onChangeProps({points:points.map(([x,y])=>[x+1,y]),labels:labels.map(label=>({...label,coord:[label.coord[0]+1,label.coord[1]]}))});break}}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:expanded,onToggle:onToggle,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$j.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:`Polygon, ${points.length} sides`}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(PolygonSwatch,{color:color,fillStyle:fillStyle,strokeStyle:strokeStyle})]}),children:[jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$j.row,styles$j.spaceUnder],children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:color,onChange:handleColorChange}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.medium_16}),jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{tag:"label",style:[styles$j.row,styles$j.truncatedWidth],children:["fill",jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxSmall_6}),jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{selectedValue:fillStyle,onChange:value=>onChangeProps({fillStyle:value}),placeholder:"",children:Object.keys(perseusCore.lockedFigureFillStyles).map(option=>jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:option,label:option},option))})]})]}),jsxRuntimeExports.jsx(LineStrokeSelect,{selectedValue:strokeStyle,onChange:value=>onChangeProps({strokeStyle:value}),containerStyle:styles$j.spaceUnder}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value}),containerStyle:styles$j.spaceUnder}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"show vertices",checked:showVertices,onChange:newValue=>onChangeProps({showVertices:newValue}),style:styles$j.spaceUnder}),jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:"Points"}),expanded:true,containerStyle:styles$j.pointAccordionContainer,panelStyle:styles$j.pointAccordionPanel,children:[points.map((point,index)=>{const pointLabel=String.fromCharCode(65+index);return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$j.row,styles$j.spaceUnder],children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",children:`${pointLabel}:`}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.medium_16}),jsxRuntimeExports.jsx(CoordinatePairInput,{coord:point,labels:["x","y"],onChange:newValue=>{const newPoints=[...points];newPoints[index]=newValue;props.onChangeProps({points:newPoints});}}),points.length>3&&jsxRuntimeExports.jsx(IconButton__default.default,{"aria-label":`Delete polygon point ${pointLabel}`,icon:minusCircle__default.default,kind:"tertiary",actionType:"destructive",onClick:()=>{const newPoints=[...points];newPoints.splice(index,1);props.onChangeProps({points:newPoints});},style:styles$j.icon})]},`locked-polygon-point-index-${index}`)}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:[styles$j.row,styles$j.polygonActionsContainer],children:[jsxRuntimeExports.jsx(Button__default.default,{kind:"tertiary",startIcon:plusCircle__default.default,onClick:()=>{props.onChangeProps({points:[...points,[0,0]]});},children:"Add point"}),jsxRuntimeExports.jsx(wonderBlocksLayout.Spring,{}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$j.movementButtonsContainer,children:[jsxRuntimeExports.jsx(IconButton__default.default,{"aria-label":"Move polygon up",size:"small",icon:arrowFatUp__default.default,kind:"tertiary",onClick:()=>handlePolygonMove("up")}),jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$j.row,children:[jsxRuntimeExports.jsx(IconButton__default.default,{"aria-label":"Move polygon left",size:"small",icon:arrowFatLeft__default.default,kind:"tertiary",onClick:()=>handlePolygonMove("left")}),jsxRuntimeExports.jsx(IconButton__default.default,{"aria-label":"Move polygon down",size:"small",icon:arrowFatDown__default.default,kind:"tertiary",onClick:()=>handlePolygonMove("down")}),jsxRuntimeExports.jsx(IconButton__default.default,{"aria-label":"Move polygon right",size:"small",icon:arrowFatRight__default.default,kind:"tertiary",onClick:()=>handlePolygonMove("right")})]})]})]})]}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$j.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$j.horizontalRule}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{children:"Visible labels"}),labels.map((label,labelIndex)=>React.createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$j.labelContainer})),jsxRuntimeExports.jsx(Button__default.default,{kind:"tertiary",startIcon:plusCircle__default.default,onClick:()=>{const newLabel={...perseusCore.getDefaultFigureForType("label"),coord:[points[0][0],points[0][1]-labels.length],color:color};onChangeProps({labels:[...labels,newLabel]});},style:styles$j.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$j=aphrodite.StyleSheet.create({row:{display:"flex",flexDirection:"row",alignItems:"center"},pointAccordionContainer:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default},pointAccordionPanel:{alignItems:"start"},icon:{marginInlineStart:wonderBlocksTokens.spacing.xxxSmall_4},polygonActionsContainer:{width:"100%"},movementButtonsContainer:{display:"flex",flexDirection:"column",alignItems:"center",minWidth:"fit-content"},spaceUnder:{marginBottom:wonderBlocksTokens.spacing.xSmall_8},truncatedWidth:{minWidth:0},addButton:{alignSelf:"start"},labelContainer:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default},horizontalRule:{height:1,backgroundColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle}});
|
|
1732
1746
|
|
|
1733
1747
|
const lengthErrorMessage="The vector cannot have length 0.";const LockedVectorSettings=props=>{const{points,color:lineColor,weight,labels,ariaLabel,onChangeProps,onMove,onRemove}=props;const[tail,tip]=points;const lineLabel=`Vector (${tail[0]}, ${tail[1]}), (${tip[0]}, ${tip[1]})`;const isInvalid=kmath.vector.equal(tail,tip);async function getPrepopulatedAriaLabel(){const visiblelabel=await joinLabelsAsSpokenMath(labels);const spokenTailX=await generateSpokenMathDetails(`$${tail[0]}$`);const spokenTailY=await generateSpokenMathDetails(`$${tail[1]}$`);const spokenTipX=await generateSpokenMathDetails(`$${tip[0]}$`);const spokenTipY=await generateSpokenMathDetails(`$${tip[1]}$`);let str=`Vector${visiblelabel} from ${spokenTailX} comma ${spokenTailY} to ${spokenTipX} comma ${spokenTipY}`;const vectorAppearance=generateLockedFigureAppearanceDescription(lineColor,"solid",undefined,weight);str+=vectorAppearance;return str}function handleChangePoint(newCoord,index){if(typeof newCoord!=="undefined"){const newPoints=[...points];newPoints[index]=[...newCoord];const oldMidpoint=mafs.vec.midpoint(tail,tip);const newMidpoint=mafs.vec.midpoint(newPoints[0],newPoints[1]);const offset=mafs.vec.sub(newMidpoint,oldMidpoint);const newLabels=labels.map(label=>({...label,coord:mafs.vec.add(label.coord,offset)}));onChangeProps({points:newPoints,labels:newLabels});}}function handleColorChange(newColor){const newProps={color:newColor};newProps.labels=labels.map(label=>({...label,color:newColor}));onChangeProps(newProps);}function handleLabelChange(updatedLabel,labelIndex){const updatedLabels=[...labels];updatedLabels[labelIndex]={...labels[labelIndex],...updatedLabel};onChangeProps({labels:updatedLabels});}function handleLabelRemove(labelIndex){const updatedLabels=labels.filter((_,index)=>index!==labelIndex);onChangeProps({labels:updatedLabels});}return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{expanded:props.expanded,onToggle:props.onToggle,header:jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:styles$i.row,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:lineLabel}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xSmall_8}),jsxRuntimeExports.jsx(LineSwatch,{color:lineColor,lineStyle:"solid"})]}),children:[jsxRuntimeExports.jsx(ColorSelect,{selectedValue:lineColor,onChange:handleColorChange,style:{marginBottom:wonderBlocksTokens.sizing.size_080}}),jsxRuntimeExports.jsx(LineWeightSelect,{selectedValue:weight,onChange:value=>onChangeProps({weight:value})}),isInvalid&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{style:styles$i.errorText,children:lengthErrorMessage}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:styles$i.container,panelStyle:styles$i.accordionPanel,header:jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$i.row,children:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:`Tail (${tail[0]}, ${tail[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tail,error:isInvalid,onChange:newProps=>{handleChangePoint(newProps,0);}})}),jsxRuntimeExports.jsx(PerseusEditorAccordion,{expanded:true,containerStyle:styles$i.container,panelStyle:styles$i.accordionPanel,header:jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$i.row,children:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"span",children:`Tip (${tip[0]}, ${tip[1]})`})}),children:jsxRuntimeExports.jsx(CoordinatePairInput,{coord:tip,error:isInvalid,onChange:newProps=>{handleChangePoint(newProps,1);}})}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$i.horizontalRule}),jsxRuntimeExports.jsx(LockedFigureAria,{ariaLabel:ariaLabel,getPrepopulatedAriaLabel:getPrepopulatedAriaLabel,onChangeProps:newProps=>{onChangeProps(newProps);}}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.xxxSmall_4}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$i.horizontalRule}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{children:"Visible labels"}),labels.map((label,labelIndex)=>React.createElement(LockedLabelSettings,{...label,key:labelIndex,expanded:true,onChangeProps:newLabel=>{handleLabelChange(newLabel,labelIndex);},onRemove:()=>{handleLabelRemove(labelIndex);},containerStyle:styles$i.labelContainer})),jsxRuntimeExports.jsx(Button__default.default,{kind:"tertiary",startIcon:plusCircle__default.default,onClick:()=>{const offsetPerLabel=[0,-1];const labelLocation=mafs.vec.add(mafs.vec.scale(offsetPerLabel,labels.length),mafs.vec.midpoint(tail,tip));const newLabel={...perseusCore.getDefaultFigureForType("label"),coord:labelLocation,color:lineColor};onChangeProps({labels:[...labels,newLabel]});},style:styles$i.addButton,children:"Add visible label"}),jsxRuntimeExports.jsx(LockedFigureSettingsActions,{figureType:props.type,onMove:onMove,onRemove:onRemove})]})};const styles$i=aphrodite.StyleSheet.create({accordionPanel:{paddingBottom:wonderBlocksTokens.spacing.medium_16},container:{marginTop:wonderBlocksTokens.spacing.xSmall_8,marginBottom:0,marginLeft:-wonderBlocksTokens.spacing.xxxSmall_4,marginRight:-wonderBlocksTokens.spacing.xxxSmall_4,backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default},errorText:{color:wonderBlocksTokens.semanticColor.core.foreground.critical.default,marginTop:wonderBlocksTokens.spacing.xSmall_8},row:{flexDirection:"row",alignItems:"center"},addButton:{alignSelf:"start"},horizontalRule:{height:1,backgroundColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle},labelContainer:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default}});
|
|
1734
1748
|
|
|
@@ -1768,7 +1782,7 @@ const StartCoordsTangent=props=>{const{startCoords,onChange}=props;return jsxRun
|
|
|
1768
1782
|
|
|
1769
1783
|
const StartCoordsSettingsInner=props=>{const{type,range,step,allowReflexAngles,onChange}=props;switch(type){case "absolute-value":const absoluteValueCoords=perseus.getAbsoluteValueCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsAbsoluteValue,{startCoords:absoluteValueCoords,onChange:onChange});case "linear":case "ray":const linearCoords=perseus.getLineCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsLine,{startCoords:linearCoords,onChange:onChange});case "linear-system":case "segment":const multiLineCoords=type==="segment"?perseus.getSegmentCoords(props,range,step):perseus.getLinearSystemCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsMultiline,{type:type,startCoords:multiLineCoords,onChange:onChange});case "circle":const circleCoords=perseus.getCircleCoords(props);const radius=kmath.vector.length(kmath.vector.subtract(circleCoords.radiusPoint,circleCoords.center));return jsxRuntimeExports.jsx(StartCoordsCircle,{startCoords:{center:circleCoords.center,radius},onChange:onChange});case "sinusoid":const sinusoidCoords=perseus.getSinusoidCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsSinusoid,{startCoords:sinusoidCoords,onChange:onChange});case "exponential":{const defaultStartCoords=getDefaultGraphStartCoords(props,range,step);const currentStartCoords=props.startCoords??defaultStartCoords;return jsxRuntimeExports.jsx(StartCoordsExponential,{startCoords:currentStartCoords,onChange:onChange})}case "logarithm":{const defaultLogarithmCoords=getDefaultGraphStartCoords(props,range,step);const currentLogarithmCoords=props.startCoords??defaultLogarithmCoords;return jsxRuntimeExports.jsx(StartCoordsLogarithm,{startCoords:currentLogarithmCoords,onChange:onChange})}case "vector":{const vectorCoords=perseus.getVectorCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsLine,{startCoords:vectorCoords,onChange:onChange})}case "tangent":const tangentCoords=perseus.getTangentCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsTangent,{startCoords:tangentCoords,onChange:onChange});case "quadratic":const quadraticCoords=perseus.getQuadraticCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsQuadratic,{startCoords:quadraticCoords,onChange:onChange});case "point":case "polygon":const pointCoords=type==="point"?perseus.getPointCoords(props,range,step):perseus.getPolygonCoords(props,range,step);return jsxRuntimeExports.jsx(StartCoordsPoint,{startCoords:pointCoords,onChange:onChange});case "angle":const angleCoords=perseus.getAngleCoords({graph:props,range,step});return jsxRuntimeExports.jsx(StartCoordsAngle,{startCoords:angleCoords,allowReflexAngles:allowReflexAngles,onChange:onChange});default:return null}};const StartCoordsSettings=props=>{const{range,step,onChange}=props;const[isOpen,setIsOpen]=React__namespace.useState(true);return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{children:[jsxRuntimeExports.jsx(Heading,{isCollapsible:true,title:"Start coordinates",isOpen:isOpen,onToggle:()=>setIsOpen(!isOpen)}),isOpen&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(StartCoordsSettingsInner,{...props}),jsxRuntimeExports.jsx(wonderBlocksLayout.Strut,{size:wonderBlocksTokens.spacing.small_12}),jsxRuntimeExports.jsx(Button__default.default,{startIcon:arrowCounterClockwise__default.default,kind:"tertiary",size:"small",onClick:()=>{onChange(getDefaultGraphStartCoords(props,range,step));},children:"Use default start coordinates"})]})]})};
|
|
1770
1784
|
|
|
1771
|
-
const InteractiveGraph=perseus.InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React__namespace.Component{serialize(){const json=___default.default.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","showAxisArrows","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();___default.default.extend(json,{graph:{type:correct.type,startCoords:this.props.graph&&getStartCoords(this.props.graph)},correct:correct});___default.default.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(___default.default.has(correct,key)){json.graph[key]=correct[key];}});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||perseus.Util.getGridStep(this.props.range,this.props.step,perseus.interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||perseus.Util.snapStepFromGridStep(gridStep);const sizeClass=perseus.containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",box:this.props.box,range:this.props.range,showAxisArrows:this.props.showAxisArrows,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,static:this.props.apiOptions?.editingDisabled??false,trackInteraction:function(){},userInput:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant__default.default(newGraph!=null);if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(wonderBlocksCore.Id,{children:graphId=>jsxRuntimeExports.jsxs(wonderBlocksCore.View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type:",children:jsxRuntimeExports.jsx(GraphTypeSelector,{graphType:this.props.graph?.type??InteractiveGraph.defaultProps.userInput.type,onChange:type=>{this.props.onChange({graph:{type},correct:{type}});},apiOptions:this.props.apiOptions})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsx(AngleAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:this.props.onChange}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,onChange:this.changeStartCoords}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:perseus.getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,showAxisArrows:this.props.showAxisArrows,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange,apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&kmath.vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}if(this.props.graph?.type==="exponential"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteY=asymptote;const minY=Math.min(coords[0][1],coords[1][1]);const maxY=Math.max(coords[0][1],coords[1][1]);if(asymptoteY>=minY&&asymptoteY<=maxY){issues.push("The exponential start asymptote must not fall between or on the curve's start points.");}}if(this.props.graph?.type==="logarithm"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteX=asymptote;const minX=Math.min(coords[0][0],coords[1][0]);const maxX=Math.max(coords[0][0],coords[1][0]);if(asymptoteX>=minX&&asymptoteX<=maxX){issues.push("The logarithm start asymptote must not fall between or on the curve's start points.");}}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.defaultProps={...perseusCore.interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant__default.default(b.type==="angle");return {...a,...b};case "circle":invariant__default.default(b.type==="circle");return {...a,...b};case "linear":invariant__default.default(b.type==="linear");return {...a,...b};case "linear-system":invariant__default.default(b.type==="linear-system");return {...a,...b};case "none":invariant__default.default(b.type==="none");return {...a,...b};case "point":invariant__default.default(b.type==="point");return {...a,...b};case "polygon":invariant__default.default(b.type==="polygon");return {...a,...b};case "quadratic":invariant__default.default(b.type==="quadratic");return {...a,...b};case "ray":invariant__default.default(b.type==="ray");return {...a,...b};case "segment":invariant__default.default(b.type==="segment");return {...a,...b};case "sinusoid":invariant__default.default(b.type==="sinusoid");return {...a,...b};case "absolute-value":invariant__default.default(b.type==="absolute-value");return {...a,...b};case "exponential":invariant__default.default(b.type==="exponential");return {...a,...b};case "tangent":invariant__default.default(b.type==="tangent");return {...a,...b};case "logarithm":invariant__default.default(b.type==="logarithm");return {...a,...b};case "vector":invariant__default.default(b.type==="vector");return {...a,...b};default:throw new wonderStuffCore.UnreachableCaseError(a)}}
|
|
1785
|
+
const InteractiveGraph=perseus.InteractiveGraphWidget.widget;class InteractiveGraphEditor extends React__namespace.Component{serialize(){const json=___default.default.pick(this.props,"step","backgroundImage","markings","labels","labelLocation","showProtractor","showTooltips","range","showAxisArrows","gridStep","snapStep","lockedFigures","fullGraphAriaLabel","fullGraphAriaDescription");const graph=this.refs.graph;if(graph){const correct=graph&&graph.getUserInput();___default.default.extend(json,{graph:{type:correct.type,startCoords:this.props.graph&&getStartCoords(this.props.graph)},correct:correct});___default.default.each(["allowReflexAngles","angleOffsetDeg","numPoints","numSides","numSegments","showAngles","showSides","snapTo","snapDegrees"],function(key){if(___default.default.has(correct,key)){json.graph[key]=correct[key];}});}return json}render(){let graph;let equationString;const gridStep=this.props.gridStep||perseus.Util.getGridStep(this.props.range,this.props.step,perseus.interactiveSizes.defaultBoxSize);const snapStep=this.props.snapStep||perseus.Util.snapStepFromGridStep(gridStep);const sizeClass=perseus.containerSizeClass.SMALL;if(this.props.valid===true){const correct=this.props.correct.type===this.props.graph?.type?this.props.correct:this.props.graph;const graphProps={ref:"graph",box:this.props.box,range:this.props.range,showAxisArrows:this.props.showAxisArrows,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,lockedFigures:this.props.lockedFigures,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,static:this.props.apiOptions?.editingDisabled??false,trackInteraction:function(){},userInput:correct,handleUserInput:newGraph=>{let correct=this.props.correct;invariant__default.default(newGraph!=null);if(correct.type===newGraph.type){correct=mergeGraphs(correct,newGraph);}else {correct=newGraph;}this.props.onChange({correct:correct,graph:this.props.graph});}};graph=jsxRuntimeExports.jsx(InteractiveGraph,{...graphProps,containerSizeClass:sizeClass,apiOptions:{...this.props.apiOptions,isMobile:false}});equationString=InteractiveGraph.getEquationString(graphProps);}else {graph=jsxRuntimeExports.jsx("div",{className:"perseus-error",children:this.props.valid});}return jsxRuntimeExports.jsx(wonderBlocksCore.Id,{children:graphId=>jsxRuntimeExports.jsxs(wonderBlocksCore.View,{children:[jsxRuntimeExports.jsx(LabeledRow,{label:"Answer type",labelSize:"medium",children:jsxRuntimeExports.jsx(GraphTypeSelector,{graphType:this.props.graph?.type??InteractiveGraph.defaultProps.userInput.type,onChange:type=>{this.props.onChange({graph:{type},correct:{type}});},apiOptions:this.props.apiOptions})}),jsxRuntimeExports.jsx(InteractiveGraphDescription,{ariaLabelValue:this.props.fullGraphAriaLabel??"",ariaDescriptionValue:this.props.fullGraphAriaDescription??"",onChange:this.props.onChange}),jsxRuntimeExports.jsx(InteractiveGraphCorrectAnswer,{id:graphId,equationString:equationString,children:graph}),this.props.correct?.type==="angle"&&jsxRuntimeExports.jsx(AngleAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="point"&&jsxRuntimeExports.jsx(GraphPointsCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="polygon"&&jsxRuntimeExports.jsx(PolygonAnswerOptions,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.correct?.type==="vector"&&jsxRuntimeExports.jsx(VectorAnswerOptions,{correct:this.props.correct,onChange:this.props.onChange}),this.props.correct?.type==="segment"&&jsxRuntimeExports.jsx(SegmentCountSelector,{correct:this.props.correct,graph:this.props.graph,onChange:this.props.onChange}),this.props.graph?.type&&shouldShowStartCoordsUI(this.props.graph,this.props.static)&&jsxRuntimeExports.jsx(StartCoordsSettings,{...this.props.graph,range:this.props.range,step:this.props.step,onChange:this.changeStartCoords}),jsxRuntimeExports.jsx(InteractiveGraphSRTree,{graphId:graphId,correct:this.props.correct,fullGraphAriaLabel:this.props.fullGraphAriaLabel,fullGraphAriaDescription:this.props.fullGraphAriaDescription,lockedFigures:this.props.lockedFigures}),jsxRuntimeExports.jsx(InteractiveGraphSettings,{box:perseus.getInteractiveBoxFromSizeClass(sizeClass),range:this.props.range,showAxisArrows:this.props.showAxisArrows,labels:this.props.labels,labelLocation:this.props.labelLocation,step:this.props.step,gridStep:gridStep,snapStep:snapStep,valid:this.props.valid,backgroundImage:this.props.backgroundImage,markings:this.props.markings,showProtractor:this.props.showProtractor,showTooltips:this.props.showTooltips,onChange:this.props.onChange,apiOptions:this.props.apiOptions}),jsxRuntimeExports.jsx(LockedFiguresSection,{figures:this.props.lockedFigures,onChange:this.props.onChange,apiOptions:this.props.apiOptions})]})})}constructor(...args){super(...args),this.displayName="InteractiveGraphEditor",this.className="perseus-widget-interactive-graph",this.changeStartCoords=coords=>{if(!this.props.graph?.type){return}const graph={...this.props.graph,startCoords:coords};this.props.onChange({graph:graph});},this.getSaveWarnings=()=>{const issues=[];for(const figure of this.props.lockedFigures??[]){if(figure.type==="line"&&kmath.vector.equal(figure.points[0].coord,figure.points[1].coord)){issues.push("The line cannot have length 0.");}}if(this.props.graph?.type==="polygon"&&this.props.graph.numSides==="unlimited"&&this.props.graph.coords===null){issues.push("Polygon must be closed.");}if(this.props.graph?.type==="exponential"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteY=asymptote;const minY=Math.min(coords[0][1],coords[1][1]);const maxY=Math.max(coords[0][1],coords[1][1]);if(asymptoteY>=minY&&asymptoteY<=maxY){issues.push("The exponential start asymptote must not fall between or on the curve's start points.");}}if(this.props.graph?.type==="logarithm"&&this.props.graph.startCoords!=null){const{coords,asymptote}=this.props.graph.startCoords;const asymptoteX=asymptote;const minX=Math.min(coords[0][0],coords[1][0]);const maxX=Math.max(coords[0][0],coords[1][0]);if(asymptoteX>=minX&&asymptoteX<=maxX){issues.push("The logarithm start asymptote must not fall between or on the curve's start points.");}}return issues};}}InteractiveGraphEditor.widgetName="interactive-graph";InteractiveGraphEditor.bestPractices={url:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/3295281289/Interactive+Graph+Widget#Adding-a-new-Interactive-Graph-Widget",label:"Interactive Graph best practices"};InteractiveGraphEditor.defaultProps={...perseusCore.interactiveGraphLogic.defaultWidgetOptions,valid:true,lockedFigures:[]};function mergeGraphs(a,b){if(a.type!==b.type){throw new Error(`Cannot merge graphs with different types (${a.type} and ${b.type})`)}switch(a.type){case "angle":invariant__default.default(b.type==="angle");return {...a,...b};case "circle":invariant__default.default(b.type==="circle");return {...a,...b};case "linear":invariant__default.default(b.type==="linear");return {...a,...b};case "linear-system":invariant__default.default(b.type==="linear-system");return {...a,...b};case "none":invariant__default.default(b.type==="none");return {...a,...b};case "point":invariant__default.default(b.type==="point");return {...a,...b};case "polygon":invariant__default.default(b.type==="polygon");return {...a,...b};case "quadratic":invariant__default.default(b.type==="quadratic");return {...a,...b};case "ray":invariant__default.default(b.type==="ray");return {...a,...b};case "segment":invariant__default.default(b.type==="segment");return {...a,...b};case "sinusoid":invariant__default.default(b.type==="sinusoid");return {...a,...b};case "absolute-value":invariant__default.default(b.type==="absolute-value");return {...a,...b};case "exponential":invariant__default.default(b.type==="exponential");return {...a,...b};case "tangent":invariant__default.default(b.type==="tangent");return {...a,...b};case "logarithm":invariant__default.default(b.type==="logarithm");return {...a,...b};case "vector":invariant__default.default(b.type==="vector");return {...a,...b};default:throw new wonderStuffCore.UnreachableCaseError(a)}}
|
|
1772
1786
|
|
|
1773
1787
|
const gray98="#FAFAFA";const gray95="#F0F1F2";const gray85="#D6D8DA";const gray76="#BABEC2";const gray68="#888D93";const gray41="#626569";const gray17="#21242C";
|
|
1774
1788
|
|
|
@@ -1838,7 +1852,7 @@ function RadioStatusPill({index,correct,multipleSelect,onClick}){return jsxRunti
|
|
|
1838
1852
|
|
|
1839
1853
|
const RadioOptionSettings=React__namespace.forwardRef(function RadioOptionSettings({index,choice,multipleSelect,onStatusChange,onContentChange,onRationaleChange,showDelete,showMove,onDelete,onMove},ref){const{content,rationale,correct,isNoneOfTheAbove}=choice;const uniqueId=React__namespace.useId();const rationaleTextAreaId=`${uniqueId}-rationale-textarea`;const contentEditorRef=React__namespace.useRef(null);React__namespace.useImperativeHandle(ref,()=>({focus:()=>{contentEditorRef.current?.focus();}}));return jsxRuntimeExports.jsxs("div",{className:styles.tile,children:[jsxRuntimeExports.jsxs("fieldset",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(RadioStatusPill,{index:index,correct:correct,multipleSelect:multipleSelect,onClick:()=>{onStatusChange(index,!correct);}}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",weight:"bold",tag:"span",style:{display:"inline",marginInlineEnd:wonderBlocksTokens.sizing.size_080},children:"Status"}),jsxRuntimeExports.jsx(Pill__default.default,{kind:correct?"accent":"transparent",onClick:()=>{onStatusChange(index,true);},style:{marginInlineEnd:wonderBlocksTokens.sizing.size_080,outlineColor:correct?wonderBlocksTokens.semanticColor.core.background.instructive.default:wonderBlocksTokens.semanticColor.core.border.neutral.default},children:"Correct"}),jsxRuntimeExports.jsx(Pill__default.default,{kind:correct?"transparent":"accent",onClick:()=>{onStatusChange(index,false);},style:{marginInlineEnd:wonderBlocksTokens.sizing.size_080,outlineColor:!correct?wonderBlocksTokens.semanticColor.core.background.instructive.default:wonderBlocksTokens.semanticColor.core.border.neutral.default},children:"Incorrect"})]}),jsxRuntimeExports.jsx(RadioOptionContentAndImageEditor,{ref:contentEditorRef,content:content,choiceIndex:index,isNoneOfTheAbove:isNoneOfTheAbove??false,onContentChange:onContentChange}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",weight:"bold",tag:"label",htmlFor:rationaleTextAreaId,style:{marginBlockStart:wonderBlocksTokens.sizing.size_040,marginBlockEnd:wonderBlocksTokens.sizing.size_040},children:"Rationale"}),jsxRuntimeExports.jsx(wonderBlocksForm.TextArea,{id:rationaleTextAreaId,value:rationale??"",placeholder:`Why is this choice ${correct?"correct":"incorrect"}?`,onChange:value=>{onRationaleChange(index,value);},autoResize:true}),jsxRuntimeExports.jsx(RadioOptionSettingsActions,{content:content,showDelete:showDelete,showMove:showMove,onDelete:onDelete,onMove:movement=>onMove(index,movement)})]})});
|
|
1840
1854
|
|
|
1841
|
-
class RadioEditor extends React__namespace.Component{componentDidMount(){if(this.props.multipleSelect&&this.props.countChoices){this.props.onChange({numCorrect:perseusCore.deriveNumCorrect(this.props.choices)});}const needsIdUpdate=this.props.choices.some(choice=>!choice.id||choice.id.trim()==="");if(needsIdUpdate){const updatedChoices=this.props.choices.map((choice,index)=>({...choice,id:this.ensureValidIds(choice.id,index)}));this.props.onChange({choices:updatedChoices});}}serialize(){const{choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled}=this.props;return {choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled,numCorrect:perseusCore.deriveNumCorrect(choices)}}render(){const numCorrect=perseusCore.deriveNumCorrect(this.props.choices);const isEditingDisabled=this.props.apiOptions.editingDisabled;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.
|
|
1855
|
+
class RadioEditor extends React__namespace.Component{componentDidMount(){if(this.props.multipleSelect&&this.props.countChoices){this.props.onChange({numCorrect:perseusCore.deriveNumCorrect(this.props.choices)});}const needsIdUpdate=this.props.choices.some(choice=>!choice.id||choice.id.trim()==="");if(needsIdUpdate){const updatedChoices=this.props.choices.map((choice,index)=>({...choice,id:this.ensureValidIds(choice.id,index)}));this.props.onChange({choices:updatedChoices});}}serialize(){const{choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled}=this.props;return {choices,randomize,multipleSelect,countChoices,hasNoneOfTheAbove,deselectEnabled,numCorrect:perseusCore.deriveNumCorrect(choices)}}render(){const numCorrect=perseusCore.deriveNumCorrect(this.props.choices);const isEditingDisabled=this.props.apiOptions.editingDisabled;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-row",children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Randomize order",checked:this.props.randomize,disabled:isEditingDisabled,onChange:value=>{this.props.onChange({randomize:value});},style:{marginBlockEnd:wonderBlocksTokens.sizing.size_060}}),jsxRuntimeExports.jsx(LabeledSwitch,{label:"Multiple selections",checked:this.props.multipleSelect,disabled:isEditingDisabled,onChange:value=>{this.onMultipleSelectChange({multipleSelect:value});},style:{marginBlockEnd:wonderBlocksTokens.sizing.size_060}}),this.props.multipleSelect&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledSwitch,{label:"Specify number correct",checked:this.props.countChoices,disabled:isEditingDisabled,onChange:value=>{this.onCountChoicesChange({countChoices:value});},style:{marginBlockEnd:wonderBlocksTokens.sizing.size_060}}),jsxRuntimeExports.jsxs(wonderBlocksTypography.BodyText,{size:"xsmall",tag:"span",children:["Current number correct: ",numCorrect]})]})]}),this.props.choices.map((choice,index)=>jsxRuntimeExports.jsx(RadioOptionSettings,{ref:this.getChoiceRef(choice.id),index:index,choice:choice,multipleSelect:this.props.multipleSelect,onStatusChange:this.onStatusChange,onContentChange:this.onContentChange,onRationaleChange:this.onRationaleChange,showDelete:this.props.choices.length>=2,showMove:this.props.choices.length>1&&!choice.isNoneOfTheAbove,onDelete:()=>this.onDelete(index),onMove:this.handleMove},`choice-${choice.id}`)),jsxRuntimeExports.jsxs("div",{className:"add-choice-container",children:[jsxRuntimeExports.jsx(Button__default.default,{size:"small",kind:"tertiary",startIcon:plusIcon__default.default,onClick:this.addChoice.bind(this,false),style:{marginInlineEnd:"2.4rem"},children:"Add a choice"}),!this.props.hasNoneOfTheAbove&&jsxRuntimeExports.jsx(Button__default.default,{size:"small",kind:"tertiary",startIcon:plusIcon__default.default,onClick:this.addChoice.bind(this,true),children:"None of the above"})]})]})}constructor(...args){super(...args),this.choiceRefs=new Map,this.getChoiceRef=choiceId=>{if(!this.choiceRefs.has(choiceId)){this.choiceRefs.set(choiceId,React__namespace.createRef());}return this.choiceRefs.get(choiceId)},this.onMultipleSelectChange=options=>{const isMultipleSelect=options.multipleSelect;let choices=this.props.choices;if(!isMultipleSelect){const numCorrect=perseusCore.deriveNumCorrect(choices);if(numCorrect>1){choices=choices.map(choice=>{return {...choice,correct:false}});}}this.props.onChange({multipleSelect:isMultipleSelect,choices,numCorrect:perseusCore.deriveNumCorrect(choices)});},this.onCountChoicesChange=options=>{const countChoices=options.countChoices;this.props.onChange({countChoices});},this.generateChoiceId=index=>{return `radio-choice-${index}`},this.ensureValidIds=(choiceId,index)=>{if(!choiceId||choiceId.trim()===""){return this.generateChoiceId(index)}return choiceId},this.onChange=({checked})=>{const choices=this.props.choices.map((choice,i)=>{return {...choice,correct:checked[i],content:choice.isNoneOfTheAbove&&!checked[i]?"":choice.content,id:this.ensureValidIds(choice.id,i)}});this.props.onChange({choices,numCorrect:perseusCore.deriveNumCorrect(choices)});},this.onStatusChange=(choiceIndex,correct)=>{let newCheckedList;if(correct&&!this.props.multipleSelect){newCheckedList=this.props.choices.map(_=>false);}else {newCheckedList=this.props.choices.map(c=>c.correct);}newCheckedList[choiceIndex]=correct;this.onChange({checked:newCheckedList});},this.onContentChange=(choiceIndex,newContent)=>{const choices=[...this.props.choices];choices[choiceIndex]={...choices[choiceIndex],content:newContent};this.props.onChange({choices:choices});},this.onRationaleChange=(choiceIndex,newRationale)=>{const choices=[...this.props.choices];choices[choiceIndex]={...choices[choiceIndex],rationale:newRationale};if(newRationale===""){delete choices[choiceIndex].rationale;}this.props.onChange({choices:choices});},this.onDelete=choiceIndex=>{const choices=this.props.choices.slice();const deleted=choices[choiceIndex];this.choiceRefs.delete(deleted.id);choices.splice(choiceIndex,1);this.props.onChange({choices,hasNoneOfTheAbove:this.props.hasNoneOfTheAbove&&!deleted.isNoneOfTheAbove,numCorrect:perseusCore.deriveNumCorrect(choices)});},this.addChoice=(noneOfTheAbove,e)=>{e.preventDefault();const choices=this.props.choices.slice();const newChoice={isNoneOfTheAbove:noneOfTheAbove,content:"",id:crypto.randomUUID()};const addIndex=choices.length-(this.props.hasNoneOfTheAbove?1:0);choices.splice(addIndex,0,newChoice);this.props.onChange({choices:choices,hasNoneOfTheAbove:noneOfTheAbove||this.props.hasNoneOfTheAbove},()=>{this.getChoiceRef(newChoice.id).current?.focus();});},this.handleMove=(choiceIndex,movement)=>{const newChoices=getMovedChoices(this.props.choices,this.props.hasNoneOfTheAbove,choiceIndex,movement);this.props.onChange({choices:newChoices});},this.focus=()=>{const firstChoice=this.props.choices[0];if(firstChoice?.id){this.getChoiceRef(firstChoice.id).current?.focus();}return true},this.getSaveWarnings=()=>{if(!___default.default.some(___default.default.pluck(this.props.choices,"correct"))){return ["No choice is marked as correct."]}return []};}}RadioEditor.widgetName="radio";RadioEditor.bestPractices={url:"https://www.khanacademy.org/internal-courses/content-creation-best-practices/xe46daa512cd9c644:question-writing/xe46daa512cd9c644:multiple-choice/a/stems",label:"Multiple choice best practices"};RadioEditor.defaultProps=perseusCore.radioLogic.defaultWidgetOptions;
|
|
1842
1856
|
|
|
1843
1857
|
const{InfoTip: InfoTip$1,TextListEditor}=perseus.components;const HORIZONTAL="horizontal";const VERTICAL="vertical";class SorterEditor extends React__namespace.Component{render(){const editor=this;return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{children:[" ","Correct answer:"," ",jsxRuntimeExports.jsx(InfoTip$1,{children:jsxRuntimeExports.jsx("p",{children:"Enter the correct answer (in the correct order) here. The preview on the right will have the cards in a randomized order, which is how the student will see them."})})]}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.correct,onChange:function(options,cb){editor.props.onChange({correct:options},cb);},layout:this.props.layout}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Layout:"," ",jsxRuntimeExports.jsxs("select",{value:this.props.layout,onChange:this.onLayoutChange,children:[jsxRuntimeExports.jsx("option",{value:HORIZONTAL,children:"Horizontal"}),jsxRuntimeExports.jsx("option",{value:VERTICAL,children:"Vertical"})]})]}),jsxRuntimeExports.jsx(InfoTip$1,{children:jsxRuntimeExports.jsx("p",{children:"Use the horizontal layout for short text and small images. The vertical layout is best for longer text and larger images."})})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(wonderBlocksForm.Checkbox,{label:"Padding:",checked:this.props.padding,onChange:value=>{this.props.onChange({padding:value});}}),jsxRuntimeExports.jsx(InfoTip$1,{children:jsxRuntimeExports.jsx("p",{children:"Padding is good for text, but not needed for images."})})]})]})}constructor(...args){super(...args),this.onLayoutChange=e=>{this.props.onChange({layout:e.target.value});},this.serialize=()=>{return ___default.default.pick(this.props,"correct","layout","padding")};}}SorterEditor.propTypes={correct:PropTypes__default.default.array,layout:PropTypes__default.default.oneOf([HORIZONTAL,VERTICAL]),padding:PropTypes__default.default.bool};SorterEditor.widgetName="sorter";SorterEditor.defaultProps=perseusCore.sorterLogic.defaultWidgetOptions;
|
|
1844
1858
|
|
|
@@ -1867,4 +1881,6 @@ exports.IframeContentRenderer = IframeContentRenderer;
|
|
|
1867
1881
|
exports.ItemDiff = ItemDiff;
|
|
1868
1882
|
exports.ViewportResizer = ViewportResizer;
|
|
1869
1883
|
exports.libVersion = libVersion;
|
|
1884
|
+
exports.usePreviewController = usePreviewController;
|
|
1885
|
+
exports.usePreviewPresenter = usePreviewPresenter;
|
|
1870
1886
|
//# sourceMappingURL=index.js.map
|