diff --git a/packages/perseus-editor/src/editor-page.test.tsx b/packages/perseus-editor/src/editor-page.test.tsx index 358f037df5..823f0a6c28 100644 --- a/packages/perseus-editor/src/editor-page.test.tsx +++ b/packages/perseus-editor/src/editor-page.test.tsx @@ -278,4 +278,62 @@ describe("EditorPage", () => { screen.getByDisplayValue(/Updated content from parent/), ).toBeInTheDocument(); }); + + it("should call getStartWidgetOptions if available", async () => { + const onChangeMock = jest.fn(); + + const startRenderer: PerseusRenderer = { + content: "That's an onomatopoeia!", + widgets: {}, + images: {}, + }; + + render( + {}} + previewDevice="desktop" + previewURL="" + itemId="itemId" + developerMode={false} + jsonMode={false} + widgetsAreOpen={true} + />, + ); + + const textarea = screen.getByRole("textbox") as HTMLTextAreaElement; + expect(textarea).toBeInTheDocument(); + + textarea.setSelectionRange(10, 22); + + const select = screen.getByTestId("editor__widget-select"); + await userEvent.selectOptions(select, "Definition"); + + expect(onChangeMock).toHaveBeenCalledWith( + { + answerArea: {}, + question: { + content: "That's an [[☃ definition 1]]!", + images: {}, + widgets: { + "definition 1": { + options: { + definition: "", + togglePrompt: "onomatopoeia", + }, + type: "definition", + version: { + major: 0, + minor: 0, + }, + }, + }, + }, + }, + expect.any(Function), + undefined, + ); + }); }); diff --git a/packages/perseus-editor/src/editor.tsx b/packages/perseus-editor/src/editor.tsx index d326963ca1..567a4ffd9a 100644 --- a/packages/perseus-editor/src/editor.tsx +++ b/packages/perseus-editor/src/editor.tsx @@ -150,6 +150,10 @@ type State = { textAreaValue: string; }; +export type StartWidgetOptionsContext = { + selectedText: string; +}; + // eslint-disable-next-line react/no-unsafe class Editor extends React.Component { lastUserValue: string | null | undefined; @@ -659,6 +663,7 @@ class Editor extends React.Component { const isBlock = CoreWidgetRegistry.getDefaultAlignment(widgetType) === "block"; + const selectedText = oldContent.slice(cursorRange[0], cursorRange[1]); const prelude = oldContent.slice(0, cursorRange[0]); const postlude = oldContent.slice(cursorRange[1]); @@ -672,8 +677,16 @@ class Editor extends React.Component { const newContent = newPrelude + widgetContent + newPostlude; const newWidgets = {...this.props.widgets}; + const widgetEditor = Widgets.getEditor(widgetType); + const startWidgetOptionsContext: StartWidgetOptionsContext = { + selectedText, + }; + const startWidgetOptions = widgetEditor?.getStartWidgetOptions?.( + startWidgetOptionsContext, + ); + const defaultProps = widgetEditor?.defaultProps; newWidgets[id] = { - options: Widgets.getEditor(widgetType)?.defaultProps, + options: startWidgetOptions || defaultProps, type: widgetType, // Track widget version on creation, so that a widget editor // without a valid version prop can only possibly refer to a @@ -860,7 +873,6 @@ class Editor extends React.Component { let pieces; let widgets; let underlayPieces; - let widgetsDropDown; let templatesDropDown; let widgetsAndTemplates; let wordCountDisplay; @@ -920,8 +932,7 @@ class Editor extends React.Component { } } - this.widgetIds = _.keys(widgets); - widgetsDropDown = ; + this.widgetIds = Object.keys(widgets); const insertTemplateString = "Insert template\u2026"; templatesDropDown = ( @@ -957,7 +968,7 @@ class Editor extends React.Component { widgetsAndTemplates = (
- {widgetsDropDown} + {templatesDropDown} {wordCountDisplay}
diff --git a/packages/perseus-editor/src/widgets/definition-editor.tsx b/packages/perseus-editor/src/widgets/definition-editor.tsx index d5e6797fd7..76eb6b909f 100644 --- a/packages/perseus-editor/src/widgets/definition-editor.tsx +++ b/packages/perseus-editor/src/widgets/definition-editor.tsx @@ -7,6 +7,7 @@ import _ from "underscore"; import Editor from "../editor"; +import type {StartWidgetOptionsContext} from "../editor"; import type {DefinitionDefaultWidgetOptions} from "@khanacademy/perseus-core"; const {TextInput} = components; @@ -31,6 +32,18 @@ class DefinitionEditor extends React.Component { static defaultProps: DefinitionDefaultWidgetOptions = definitionLogic.defaultWidgetOptions; + static getStartWidgetOptions(context: StartWidgetOptionsContext) { + const defaultWidgetOptions = { + ...definitionLogic.defaultWidgetOptions, + }; + + if (context.selectedText) { + defaultWidgetOptions.togglePrompt = context.selectedText; + } + + return defaultWidgetOptions; + } + change: (arg1: any, arg2: any, arg3: any) => any = (...args) => { return Changeable.change.apply(this, args); };