@khanacademy/perseus-editor 31.1.0 → 31.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/article-editor.d.ts +5 -0
- package/dist/editor-page.d.ts +5 -0
- package/dist/editor.d.ts +5 -0
- package/dist/es/index.js +16 -4
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +17 -3
- 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 +0 -8
- package/dist/widgets/interactive-graph-editor/interactive-graph-editor.d.ts +73 -73
- package/package.json +8 -8
package/dist/article-editor.d.ts
CHANGED
|
@@ -53,6 +53,11 @@ export default class ArticleEditor extends React.Component<Props, State> {
|
|
|
53
53
|
_handleMoveSectionLater(i: number): void;
|
|
54
54
|
_handleAddSectionAfter(i: number): void;
|
|
55
55
|
_handleRemoveSection(i: number): void;
|
|
56
|
+
/**
|
|
57
|
+
* Returns the current version of the edited {@link PerseusArticle}.
|
|
58
|
+
*
|
|
59
|
+
* @deprecated Use the {@link Props.onChange} prop instead.
|
|
60
|
+
*/
|
|
56
61
|
serialize(): PerseusArticle;
|
|
57
62
|
/**
|
|
58
63
|
* Returns an array, with one element be section.
|
package/dist/editor-page.d.ts
CHANGED
|
@@ -89,6 +89,11 @@ declare class EditorPage extends React.Component<Props, State> {
|
|
|
89
89
|
updateRenderer(): void;
|
|
90
90
|
getApiOptions(): APIOptionsWithDefaults;
|
|
91
91
|
getSaveWarnings(): any;
|
|
92
|
+
/**
|
|
93
|
+
* Returns the current version of the edited {@link PerseusItem}.
|
|
94
|
+
*
|
|
95
|
+
* @deprecated Use the {@link Props.onChange} prop instead.
|
|
96
|
+
*/
|
|
92
97
|
serialize(): PerseusItem;
|
|
93
98
|
handleChange: (toChange: OnChangeParams) => void;
|
|
94
99
|
changeJSON: (newJson: PerseusItem) => void;
|
package/dist/editor.d.ts
CHANGED
|
@@ -75,6 +75,11 @@ declare class Editor extends React.Component<Props, State> {
|
|
|
75
75
|
private getWidgetsReferencedIn;
|
|
76
76
|
focus: () => void;
|
|
77
77
|
focusAndMoveToEnd: () => void;
|
|
78
|
+
/**
|
|
79
|
+
* Returns the current version of the edited {@link PerseusRenderer}.
|
|
80
|
+
*
|
|
81
|
+
* @deprecated Use the `Props.onChange` prop instead.
|
|
82
|
+
*/
|
|
78
83
|
serialize(): PerseusRenderer;
|
|
79
84
|
render(): React.ReactNode;
|
|
80
85
|
}
|
package/dist/es/index.js
CHANGED
|
@@ -34,10 +34,10 @@ import { Checkbox as Checkbox$1, TextField, LabeledTextField, TextArea } from '@
|
|
|
34
34
|
import * as axeCore from 'axe-core';
|
|
35
35
|
import { StatefulKeypadContextProvider, KeypadContext } from '@khanacademy/keypad-context';
|
|
36
36
|
import { MobileKeypad, useMathInputI18n, createMathField } from '@khanacademy/math-input';
|
|
37
|
+
import { UnreachableCaseError, isTruthy } from '@khanacademy/wonder-stuff-core';
|
|
37
38
|
import PropTypes from 'prop-types';
|
|
38
39
|
import ReactDOM from 'react-dom';
|
|
39
40
|
import * as KAS from '@khanacademy/kas';
|
|
40
|
-
import { isTruthy, UnreachableCaseError } from '@khanacademy/wonder-stuff-core';
|
|
41
41
|
import { LabeledField } from '@khanacademy/wonder-blocks-labeled-field';
|
|
42
42
|
import plusCircle from '@phosphor-icons/core/regular/plus-circle.svg';
|
|
43
43
|
import trashIcon$1 from '@phosphor-icons/core/regular/trash.svg';
|
|
@@ -65,7 +65,7 @@ import xIcon from '@phosphor-icons/core/regular/x.svg';
|
|
|
65
65
|
import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
|
|
66
66
|
import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
|
|
67
67
|
|
|
68
|
-
const libName="@khanacademy/perseus-editor";const libVersion="31.1
|
|
68
|
+
const libName="@khanacademy/perseus-editor";const libVersion="31.2.1";addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
69
69
|
|
|
70
70
|
var jsxRuntime = {exports: {}};
|
|
71
71
|
|
|
@@ -1509,6 +1509,18 @@ const{HUD}=components;class EditorPage extends React.Component{componentDidMount
|
|
|
1509
1509
|
|
|
1510
1510
|
function ContentPreview({question,apiOptions,seamless,linterContext,legacyPerseusLint,previewDevice,reviewMode}){const i18n=usePerseusI18n();const isMobile=previewDevice!=="desktop";const className=isMobile?"perseus-mobile":"";return jsxRuntimeExports.jsx(View,{className:`framework-perseus ${className}`,style:[styles$N.container,!seamless?styles$N.gutter:undefined],children:jsxRuntimeExports.jsx(StatefulKeypadContextProvider,{children:jsxRuntimeExports.jsx(KeypadContext.Consumer,{children:({setKeypadActive,keypadElement,setKeypadElement})=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(UserInputManager,{widgets:question?.widgets||{},problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{strings:i18n.strings,apiOptions:{...apiOptions,isMobile},keypadElement:keypadElement,linterContext:linterContext,legacyPerseusLint:legacyPerseusLint,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,reviewMode:reviewMode,...question})}),jsxRuntimeExports.jsx(MobileKeypad,{onAnalyticsEvent:()=>Promise.resolve(),onDismiss:()=>setKeypadActive(false),onElementMounted:setKeypadElement})]})})})})}const styles$N=StyleSheet.create({container:{padding:spacing.xxxSmall_4,containerType:"inline-size",containerName:"perseus-root"},gutter:{marginRight:lintGutterWidth}});
|
|
1511
1511
|
|
|
1512
|
+
const PREVIEW_MESSAGE_SOURCE="perseus-preview";function createPreviewIframeReadyMessage(){return {source:PREVIEW_MESSAGE_SOURCE,type:"iframe-ready"}}
|
|
1513
|
+
|
|
1514
|
+
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}
|
|
1515
|
+
|
|
1516
|
+
function sanitizeApiOptions(apiOptions){if(apiOptions==null){return null}const{onFocusChange:_,answerableCallback:__,getAnotherHint:___,interactionCallback:____,imagePreloader:_____,trackInteraction:______,setDrawingAreaAvailable:________,baseElements:_________,nativeKeypadProxy:__________,imagePlaceholder:___________,widgetPlaceholder:____________,...serializableOptions}=apiOptions;return serializableOptions}
|
|
1517
|
+
|
|
1518
|
+
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}
|
|
1519
|
+
|
|
1520
|
+
function usePreviewController(iframeRef){const[height,setHeight]=React.useState(null);const[isIframeReady,setIsIframeReady]=React.useState(false);const pendingDataRef=React.useRef(null);React.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 UnreachableCaseError(message)}};window.addEventListener("message",handleMessage);return ()=>{window.removeEventListener("message",handleMessage);}},[iframeRef]);const sendData=React.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}}
|
|
1521
|
+
|
|
1522
|
+
function usePreviewPresenter(){const[data,setData]=React.useState(null);const iframe=window.frameElement;if(iframe==null){throw new Error("usePreviewPresenter must be used within an iframe")}React.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 UnreachableCaseError(message.type)}};window.addEventListener("message",handleMessage);window.parent.postMessage(createPreviewIframeReadyMessage(),"/");return ()=>{window.removeEventListener("message",handleMessage);}},[]);const reportHeight=React.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}}
|
|
1523
|
+
|
|
1512
1524
|
const{TextListEditor: TextListEditor$4}=components;const Categorizer=Categorizer$1.widget;class CategorizerEditor extends React.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(Checkbox$1,{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:_.first(this.props.values,items.length)});},layout:"vertical"}),jsxRuntimeExports.jsx(Categorizer,{...categorizerProps})]})}constructor(...args){super(...args),this.change=(...args)=>{return Changeable.change.apply(this,args)},this.serialize=()=>{return EditorJsonify.serialize.call(this)};}}CategorizerEditor.propTypes={...Changeable.propTypes,apiOptions:ApiOptions.propTypes,items:PropTypes.arrayOf(PropTypes.string),categories:PropTypes.arrayOf(PropTypes.string),values:PropTypes.arrayOf(PropTypes.number),randomizeItems:PropTypes.bool};CategorizerEditor.widgetName="categorizer";CategorizerEditor.defaultProps=categorizerLogic.defaultWidgetOptions;
|
|
1513
1525
|
|
|
1514
1526
|
class BlurInput extends React.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.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};}}
|
|
@@ -1604,7 +1616,7 @@ const UNLIMITED="unlimited";const parsePointCount=points=>{const parsed=parseInt
|
|
|
1604
1616
|
|
|
1605
1617
|
const GraphPointsCountSelector=({correct,graph,onChange})=>{return jsxRuntimeExports.jsx(LabeledRow,{label:"Number of Points:",children:jsxRuntimeExports.jsx(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(OptionItem,{value:`${n}`,label:`${n} point${n>1?"s":""}`},n)),jsxRuntimeExports.jsx(OptionItem,{value:UNLIMITED,label:"unlimited"},"unlimited")]})})};
|
|
1606
1618
|
|
|
1607
|
-
const GraphTypeSelector=props=>{const
|
|
1619
|
+
const GraphTypeSelector=props=>{const showVector=isFeatureOn({apiOptions:props.apiOptions},"interactive-graph-vector");return jsxRuntimeExports.jsxs(SingleSelect,{selectedValue:props.graphType,onChange:props.onChange,placeholder:"Select an answer type",style:styles$E.singleSelectShort,children:[jsxRuntimeExports.jsx(OptionItem,{value:"absolute-value",label:"Absolute value"}),jsxRuntimeExports.jsx(OptionItem,{value:"none",label:"None"}),jsxRuntimeExports.jsx(OptionItem,{value:"linear",label:"Linear function"}),jsxRuntimeExports.jsx(OptionItem,{value:"quadratic",label:"Quadratic function"}),jsxRuntimeExports.jsx(OptionItem,{value:"sinusoid",label:"Sinusoid function"}),jsxRuntimeExports.jsx(OptionItem,{value:"exponential",label:"Exponential function"}),jsxRuntimeExports.jsx(OptionItem,{value:"tangent",label:"Tangent function"}),jsxRuntimeExports.jsx(OptionItem,{value:"logarithm",label:"Logarithm function"}),jsxRuntimeExports.jsx(OptionItem,{value:"circle",label:"Circle"}),jsxRuntimeExports.jsx(OptionItem,{value:"point",label:"Point(s)"}),jsxRuntimeExports.jsx(OptionItem,{value:"linear-system",label:"Linear System"}),jsxRuntimeExports.jsx(OptionItem,{value:"polygon",label:"Polygon"}),jsxRuntimeExports.jsx(OptionItem,{value:"segment",label:"Line Segment(s)"}),jsxRuntimeExports.jsx(OptionItem,{value:"ray",label:"Ray"}),showVector&&jsxRuntimeExports.jsx(OptionItem,{value:"vector",label:"Vector"}),jsxRuntimeExports.jsx(OptionItem,{value:"angle",label:"Angle"})]})};const styles$E=StyleSheet.create({singleSelectShort:{height:sizing.size_260}});
|
|
1608
1620
|
|
|
1609
1621
|
function Heading({title,isOpen,isCollapsible,onToggle}){return jsxRuntimeExports.jsx(Clickable,{style:[styles$D.container,!isCollapsible&&styles$D.notClickable],disabled:!isCollapsible,onClick:()=>isCollapsible&&onToggle?.(!isOpen),children:()=>jsxRuntimeExports.jsxs(View,{style:styles$D.heading,children:[jsxRuntimeExports.jsx(BodyText,{size:"small",weight:"bold",tag:"span",children:title}),isCollapsible&&jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:isOpen})]})})}const styles$D=StyleSheet.create({container:{marginTop:spacing.small_12,marginInline:-10,backgroundColor:semanticColor.core.background.neutral.subtle,padding:spacing.xSmall_8,width:"calc(100% + 20px)"},heading:{flexDirection:"row",justifyContent:"space-between",userSelect:"none"},notClickable:{color:"inherit",cursor:"default"}});
|
|
1610
1622
|
|
|
@@ -1787,5 +1799,5 @@ var AllEditors = [CategorizerEditor,CSProgramEditor,DefinitionEditor,DropdownEdi
|
|
|
1787
1799
|
|
|
1788
1800
|
Widgets.registerEditors(AllEditors);Widgets.registerWidgets(widgets);Widgets.replaceDeprecatedWidgets();Widgets.replaceDeprecatedEditors();
|
|
1789
1801
|
|
|
1790
|
-
export { AllEditors, ArticleDiff, ArticleEditor, ContentPreview, DeviceFramer, Editor, EditorPage, IframeContentRenderer, ItemDiff, ViewportResizer, libVersion };
|
|
1802
|
+
export { AllEditors, ArticleDiff, ArticleEditor, ContentPreview, DeviceFramer, Editor, EditorPage, IframeContentRenderer, ItemDiff, ViewportResizer, libVersion, usePreviewController, usePreviewPresenter };
|
|
1791
1803
|
//# sourceMappingURL=index.js.map
|