@khanacademy/perseus-editor 27.4.1 → 27.5.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/index.js
CHANGED
|
@@ -124,7 +124,7 @@ var xIcon__default = /*#__PURE__*/_interopDefaultCompat(xIcon);
|
|
|
124
124
|
var checkIcon__default = /*#__PURE__*/_interopDefaultCompat(checkIcon);
|
|
125
125
|
var minusCircleIcon__default = /*#__PURE__*/_interopDefaultCompat(minusCircleIcon);
|
|
126
126
|
|
|
127
|
-
const libName="@khanacademy/perseus-editor";const libVersion="27.
|
|
127
|
+
const libName="@khanacademy/perseus-editor";const libVersion="27.5.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
128
128
|
|
|
129
129
|
var jsxRuntime = {exports: {}};
|
|
130
130
|
|
|
@@ -1573,9 +1573,9 @@ const AutoResizingTextArea=props=>{const textAreaRef=React__namespace.useRef(nul
|
|
|
1573
1573
|
|
|
1574
1574
|
var styles$K = {"labelWithInfoTip":"perseus_yoPGwqna","dimensionsContainer":"perseus_4qo24hC2"};
|
|
1575
1575
|
|
|
1576
|
-
const{InfoTip: InfoTip$k}=perseus.components;function ImageSettings({alt,backgroundImage,caption,onChange}){const uniqueId=React__namespace.useId();const altId=`${uniqueId}-alt`;const captionId=`${uniqueId}-caption`;if(!backgroundImage.url){return null}const dimensions=`${backgroundImage.width} x ${backgroundImage.height}`;const dimensionString=backgroundImage.width&&backgroundImage.height?dimensions:"unknown";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[!perseus.Util.isLabeledSVG(backgroundImage.url)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{style:{paddingBlockStart:0,marginBlockStart:wonderBlocksTokens.sizing.size_120,marginBlockEnd:wonderBlocksTokens.sizing.size_040,color:"var(--wb-semanticColor-core-foreground-neutral-strong)"},children:"Preview:"}),jsxRuntimeExports.jsx("img",{alt:`Preview: ${alt??"No alt text"}`,src:backgroundImage.url,style:{width:"100%"}})]}),jsxRuntimeExports.jsxs("div",{className:styles$K.dimensionsContainer,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{style:{padding:0,marginInlineEnd:wonderBlocksTokens.sizing.size_080,color:"var(--wb-semanticColor-core-foreground-neutral-strong)"},children:"Dimensions:"}),dimensionString]}),jsxRuntimeExports.jsxs("div",{className:styles$K.labelWithInfoTip,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:altId,children:"Alt text:"}),jsxRuntimeExports.jsx(InfoTip$k,{children:"This is important for screenreaders. The content of this alt text will be formatted as markdown (tables, emphasis, etc. are supported)."})]}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:altId,value:alt??"",onChange:value=>onChange({alt:value
|
|
1576
|
+
const{InfoTip: InfoTip$k}=perseus.components;function ImageSettings({alt,backgroundImage,caption,title,onChange}){const uniqueId=React__namespace.useId();const altId=`${uniqueId}-alt`;const titleId=`${uniqueId}-title`;const captionId=`${uniqueId}-caption`;if(!backgroundImage.url){return null}const dimensions=`${backgroundImage.width} x ${backgroundImage.height}`;const dimensionString=backgroundImage.width&&backgroundImage.height?dimensions:"unknown";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[!perseus.Util.isLabeledSVG(backgroundImage.url)&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{style:{paddingBlockStart:0,marginBlockStart:wonderBlocksTokens.sizing.size_120,marginBlockEnd:wonderBlocksTokens.sizing.size_040,color:"var(--wb-semanticColor-core-foreground-neutral-strong)"},children:"Preview:"}),jsxRuntimeExports.jsx("img",{alt:`Preview: ${alt??"No alt text"}`,src:backgroundImage.url,style:{width:"100%"}})]}),jsxRuntimeExports.jsxs("div",{className:styles$K.dimensionsContainer,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{style:{padding:0,marginInlineEnd:wonderBlocksTokens.sizing.size_080,color:"var(--wb-semanticColor-core-foreground-neutral-strong)"},children:"Dimensions:"}),dimensionString]}),jsxRuntimeExports.jsxs("div",{className:styles$K.labelWithInfoTip,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:altId,children:"Alt text:"}),jsxRuntimeExports.jsx(InfoTip$k,{children:"This is important for screenreaders. The content of this alt text will be formatted as markdown (tables, emphasis, etc. are supported)."})]}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:altId,value:alt??"",onChange:value=>onChange({alt:value}),style:textAreaStyle}),jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:titleId,children:"Title:"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:titleId,value:title??"",onChange:value=>onChange({title:value}),style:textAreaStyle}),jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:captionId,children:"Caption:"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:captionId,value:caption??"",onChange:value=>onChange({caption:value}),style:textAreaStyle})]})}const textAreaStyle={marginBlockStart:wonderBlocksTokens.sizing.size_040,marginBlockEnd:wonderBlocksTokens.sizing.size_120};
|
|
1577
1577
|
|
|
1578
|
-
const{InfoTip: InfoTip$j}=perseus.components;const INTERNALLY_HOSTED_DOMAINS="("+"ka-.*.s3.amazonaws.com|"+"(fastly|cdn).kastatic.org|"+"khanacademy.org|"+"kasandbox.org"+")";const INTERNALLY_HOSTED_URL_RE=new RegExp("^(https?|web\\+graphie)://[^/]*"+INTERNALLY_HOSTED_DOMAINS);function ImageUrlInput({backgroundImage,onChange}){const uniqueId=React__namespace.default.useId();const urlId=`${uniqueId}-url`;const[urlFieldValue,setUrlFieldValue]=React__namespace.default.useState(backgroundImage.url||"");const[backgroundImageError,setBackgroundImageError]=React__namespace.default.useState(null);function setUrl(url,width,height){const image={...backgroundImage};image.url=url;image.width=width;image.height=height;const box=[image.width,image.height];onChange({backgroundImage:image,box:box});}async function onUrlChange(url){if(!url){setBackgroundImageError(null);
|
|
1578
|
+
const{InfoTip: InfoTip$j}=perseus.components;const INTERNALLY_HOSTED_DOMAINS="("+"ka-.*.s3.amazonaws.com|"+"(fastly|cdn).kastatic.org|"+"khanacademy.org|"+"kasandbox.org"+")";const INTERNALLY_HOSTED_URL_RE=new RegExp("^(https?|web\\+graphie)://[^/]*"+INTERNALLY_HOSTED_DOMAINS);function ImageUrlInput({backgroundImage,onChange}){const uniqueId=React__namespace.default.useId();const urlId=`${uniqueId}-url`;const[urlFieldValue,setUrlFieldValue]=React__namespace.default.useState(backgroundImage.url||"");const[backgroundImageError,setBackgroundImageError]=React__namespace.default.useState(null);function setUrl(url,width,height){const image={...backgroundImage};image.url=url;image.width=width;image.height=height;const box=[image.width,image.height];onChange({backgroundImage:image,box:box});}async function onUrlChange(url){if(!url){setBackgroundImageError(null);setUrl(url,0,0);return}if(url&&!INTERNALLY_HOSTED_URL_RE.test(url)){setBackgroundImageError("Images must be from sites hosted by Khan Academy. "+"Please input a Khan Academy-owned address, or use the "+"Add Image tool to rehost an existing image");return}setBackgroundImageError(null);try{const size=await perseus.Util.getImageSizeModern(url);setUrl(url,size[0],size[1]);}catch(error){setBackgroundImageError(`There was an error loading the image URL: ${JSON.stringify(error,null,2)}`);}}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("div",{className:styles$K.labelWithInfoTip,children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:urlId,children:"Image url:"}),jsxRuntimeExports.jsx(InfoTip$j,{children:"Paste an image or graphie image URL."})]}),backgroundImageError&&jsxRuntimeExports.jsx(Banner__default.default,{kind:"critical",layout:"floating",text:backgroundImageError}),jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{id:urlId,value:urlFieldValue,onBlur:e=>onUrlChange(e.target.value),onChange:value=>setUrlFieldValue(value),style:{marginBlockStart:wonderBlocksTokens.sizing.size_040,marginBlockEnd:wonderBlocksTokens.sizing.size_080}})]})}
|
|
1579
1579
|
|
|
1580
1580
|
class ImageEditor extends React__namespace.Component{serialize(){return perseus.EditorJsonify.serialize.call(this)}render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-image-editor",children:[jsxRuntimeExports.jsx(ImageUrlInput,{...this.props}),this.props.backgroundImage.url&&jsxRuntimeExports.jsx(ImageSettings,{...this.props})]})}}ImageEditor.displayName="ImageEditor";ImageEditor.widgetName="image";ImageEditor.defaultProps=perseusCore.imageLogic.defaultWidgetOptions;
|
|
1581
1581
|
|
|
@@ -1774,7 +1774,7 @@ function RadioImageEditor({initialImageUrl,initialImageAltText,containerClassNam
|
|
|
1774
1774
|
function getMovedChoices(choices,hasNoneOfTheAbove,choiceIndex,movement){const newChoices=[...choices];const[removedChoice]=newChoices.splice(choiceIndex,1);switch(movement){case "top":if(choiceIndex===0){return choices}newChoices.unshift(removedChoice);break;case "up":if(choiceIndex===0){return choices}newChoices.splice(choiceIndex-1,0,removedChoice);break;case "down":if(choiceIndex===choices.length-1){return choices}if(choiceIndex===choices.length-2&&hasNoneOfTheAbove){return choices}newChoices.splice(choiceIndex+1,0,removedChoice);break;case "bottom":if(choiceIndex===choices.length-1){return choices}if(hasNoneOfTheAbove){const removedNoneOfTheAbove=newChoices.pop();newChoices.push(removedChoice);if(removedNoneOfTheAbove){newChoices.push(removedNoneOfTheAbove);}}else {newChoices.push(removedChoice);}break}return newChoices}function setImageProxyFromMarkdownContent(markdownContent){const images=[];const parsedMarkdown=perseus.PerseusMarkdown.parse(markdownContent,{});perseus.PerseusMarkdown.traverseContent(parsedMarkdown,node=>{if(node.type==="image"){images.push({url:node.target||"",altText:node.alt||""});}});let proxiedContent=markdownContent;images.forEach((image,index)=>{const originalPattern=``;const replacement=`![Image ${index+1}]`;const patternIndex=proxiedContent.indexOf(originalPattern);if(patternIndex!==-1){proxiedContent=proxiedContent.substring(0,patternIndex)+replacement+proxiedContent.substring(patternIndex+originalPattern.length);}});return [proxiedContent,images]}function setMarkdownContentFromImageProxy(proxiedContent,images){let markdownContent=proxiedContent;for(let i=0;i<images.length;i++){const image=images[i];markdownContent=markdownContent.replace(`![Image ${i+1}]`,``);}return markdownContent}
|
|
1775
1775
|
|
|
1776
1776
|
const RadioOptionContentAndImageEditor=props=>{const{content,choiceIndex,onContentChange,isNoneOfTheAbove}=props;const uniqueId=React__namespace.useId();const contentTextAreaId=`${uniqueId}-content-textarea`;const[proxiedContent,setProxiedContent]=React__namespace.useState("");const[images,setImages]=React__namespace.useState([]);const[addingImage,setAddingImage]=React__namespace.useState(false);React__namespace.useEffect(()=>{const[proxiedContent,images]=setImageProxyFromMarkdownContent(content??"");setProxiedContent(proxiedContent);setImages(images);},[content]);const handleAddImage=(choiceIndex,imageUrl,imageAltText)=>{const newContent=`${content}
|
|
1777
|
-
`;onContentChange(choiceIndex,newContent);};const handleDeleteImage=imageIndex=>{const substr=`![Image ${imageIndex+1}]`;const newProxiedContent=proxiedContent.replace(substr,"");setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handleUpdateImage=(imageIndex,url,altText)=>{const newImages=[...images];newImages[imageIndex]={url,altText};setImages(newImages);const newContent=setMarkdownContentFromImageProxy(proxiedContent,newImages);onContentChange(choiceIndex,newContent);};const handleContentChange=(choiceIndex,newProxiedContent)=>{setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handlePaste=e=>{const imageURL=e.clipboardData.getData("text");if(imageURL.includes("cdn.kastatic.org")||imageURL.includes("graphie")){e.preventDefault();handleAddImage(choiceIndex,imageURL,"");}};const handleDeleteImageConfirmation=imageIndex=>{if(window.confirm("Are you sure you want to delete this image?")){handleDeleteImage(imageIndex);}};if(isNoneOfTheAbove){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:"None of the above",disabled:true,onChange:()=>{}})]})}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,style:{marginBlockEnd:wonderBlocksTokens.sizing.size_040},children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:proxiedContent,placeholder:"Type a choice here...",onChange:value=>{handleContentChange(choiceIndex,value);},onPaste:handlePaste}),!addingImage&&jsxRuntimeExports.jsx(Button__default.default,{startIcon:plusIcon__default.default,size:"small",kind:"tertiary",style:{alignSelf:"flex-start"},onClick:()=>{setAddingImage(true);},children:"Add image"}),addingImage&&jsxRuntimeExports.jsx(RadioImageEditor,{initialImageUrl:"",initialImageAltText:"",containerClassName:styles.imageEditorContainer,onSave:(imageUrl,imageAltText)=>{handleAddImage(choiceIndex,imageUrl,imageAltText);},onClose:()=>{setAddingImage(false);}}),images?.map((image,imageIndex)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:`Image ${imageIndex+1}`,expanded:true,containerStyle:{backgroundColor:wonderBlocksTokens.semanticColor.
|
|
1777
|
+
`;onContentChange(choiceIndex,newContent);};const handleDeleteImage=imageIndex=>{const substr=`![Image ${imageIndex+1}]`;const newProxiedContent=proxiedContent.replace(substr,"");setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handleUpdateImage=(imageIndex,url,altText)=>{const newImages=[...images];newImages[imageIndex]={url,altText};setImages(newImages);const newContent=setMarkdownContentFromImageProxy(proxiedContent,newImages);onContentChange(choiceIndex,newContent);};const handleContentChange=(choiceIndex,newProxiedContent)=>{setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handlePaste=e=>{const imageURL=e.clipboardData.getData("text");if(imageURL.includes("cdn.kastatic.org")||imageURL.includes("graphie")){e.preventDefault();handleAddImage(choiceIndex,imageURL,"");}};const handleDeleteImageConfirmation=imageIndex=>{if(window.confirm("Are you sure you want to delete this image?")){handleDeleteImage(imageIndex);}};if(isNoneOfTheAbove){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:"None of the above",disabled:true,onChange:()=>{}})]})}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,style:{marginBlockEnd:wonderBlocksTokens.sizing.size_040},children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:proxiedContent,placeholder:"Type a choice here...",onChange:value=>{handleContentChange(choiceIndex,value);},onPaste:handlePaste}),!addingImage&&jsxRuntimeExports.jsx(Button__default.default,{startIcon:plusIcon__default.default,size:"small",kind:"tertiary",style:{alignSelf:"flex-start"},onClick:()=>{setAddingImage(true);},children:"Add image"}),addingImage&&jsxRuntimeExports.jsx(RadioImageEditor,{initialImageUrl:"",initialImageAltText:"",containerClassName:styles.imageEditorContainer,onSave:(imageUrl,imageAltText)=>{handleAddImage(choiceIndex,imageUrl,imageAltText);},onClose:()=>{setAddingImage(false);}}),images?.map((image,imageIndex)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:`Image ${imageIndex+1}`,expanded:true,containerStyle:{backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default,marginBlockStart:wonderBlocksTokens.sizing.size_040,marginBlockEnd:wonderBlocksTokens.sizing.size_040},panelStyle:{paddingBlockEnd:wonderBlocksTokens.sizing.size_120},children:[jsxRuntimeExports.jsx("img",{src:image.url,alt:image.altText,style:{marginBlockEnd:wonderBlocksTokens.sizing.size_080}}),jsxRuntimeExports.jsx(RadioImageEditor,{initialImageUrl:image.url,initialImageAltText:image.altText,onSave:(imageUrl,imageAltText)=>{handleUpdateImage(imageIndex,imageUrl,imageAltText);},onDelete:()=>{handleDeleteImageConfirmation(imageIndex);}})]},image.url))??null]})};
|
|
1778
1778
|
|
|
1779
1779
|
function RadioOptionSettingsActions({content,showDelete,showMove,onDelete,onMove}){return jsxRuntimeExports.jsxs("div",{className:styles.radioOptionActionsContainer,children:[showDelete&&jsxRuntimeExports.jsx(Button__default.default,{size:"small",kind:"tertiary",startIcon:trashIcon__default$1.default,onClick:()=>{if(window.confirm(`Are you sure you want to remove this choice?
|
|
1780
1780
|
|