diff --git a/src/stories/hello.stories.tsx b/src/stories/hello.stories.tsx index eb4514a0..7f5c0c11 100644 --- a/src/stories/hello.stories.tsx +++ b/src/stories/hello.stories.tsx @@ -56,3 +56,14 @@ export function GetValueWithButton() { ) } + +export function SetValueWithButton() { + const ref = React.useRef(null) + + return ( +
+ + +
+ ) +} diff --git a/src/system/Editor.ts b/src/system/Editor.ts index 2a5b64e3..1fb76be3 100644 --- a/src/system/Editor.ts +++ b/src/system/Editor.ts @@ -37,6 +37,7 @@ import * as Mdast from 'mdast' import { createEmptyHistoryState } from '@lexical/react/LexicalHistoryPlugin' import { MarkdownParseOptions } from '../import' import { ExportMarkdownFromLexicalOptions } from '../export/export' +import { importMarkdownToLexical } from '../import' type Teardowns = Array<() => void> @@ -62,6 +63,7 @@ function seedTable(): Mdast.Table { export const [EditorSystem, EditorSystemType] = system((r) => { const editor = r.node(null, true) const markdownSource = r.node('') + const setMarkdown = r.node() const historyState = r.node(createEmptyHistoryState()) const activeEditor = r.derive(editor, null) @@ -105,6 +107,18 @@ export const [EditorSystem, EditorSystemType] = system((r) => { editorSubscriptions ) + r.sub(r.pipe(setMarkdown, r.o.withLatestFrom(editor, markdownParseOptions)), ([markdown, editor, markdownParseOptions]) => { + r.pub(markdownSource, markdown) + editor?.update(() => { + $getRoot().clear() + importMarkdownToLexical({ + root: $getRoot(), + markdown, + ...markdownParseOptions! + }) + }) + }) + r.sub(r.pipe(applyListType, r.o.withLatestFrom(activeEditor)), ([listType, theEditor]) => { theEditor?.dispatchCommand(ListTypeCommandMap.get(listType)!, undefined) }) @@ -349,6 +363,7 @@ export const [EditorSystem, EditorSystemType] = system((r) => { lexicalNodes, imageAutocompleteSuggestions, markdownSource, + setMarkdown, imageUploadHandler } }, []) diff --git a/src/system/ViewMode.ts b/src/system/ViewMode.ts index d6063a64..ed15fe97 100644 --- a/src/system/ViewMode.ts +++ b/src/system/ViewMode.ts @@ -1,15 +1,15 @@ -import { $getRoot } from 'lexical' import { system } from '../gurx' -import { importMarkdownToLexical } from '../import' import { ViewMode } from '../types/ViewMode' -import { getStateAsMarkdown } from '../utils/lexicalHelpers' import { EditorSystemType } from './Editor' import { JsxSystemType } from './Jsx' export const [ViewModeSystem] = system( - (r, [{ editor, markdownParseOptions, markdownSource }, {}]) => { + (r, [{ markdownSource, setMarkdown }, {}]) => { const viewMode = r.node('editor') const headMarkdown = r.node('') + const markdownSourceFromEditor = r.node('') + + r.link(markdownSource, markdownSourceFromEditor) r.sub( r.pipe( @@ -23,25 +23,18 @@ export const [ViewModeSystem] = system( }, { current: 'editor' as ViewMode, next: 'editor' as ViewMode } ), - r.o.withLatestFrom(editor, markdownSource, markdownParseOptions) + r.o.withLatestFrom(markdownSourceFromEditor) ), - ([{ current }, editor, markdownSource, markdownParseOptions]) => { + ([{ current }, markdownSourceFromEditor]) => { if (current === 'markdown') { - // we're switching away from the markdown editor, convert the source back to lexical nodes. - editor?.update(() => { - $getRoot().clear() - importMarkdownToLexical({ - root: $getRoot(), - markdown: markdownSource, - ...markdownParseOptions! - }) - }) + r.pub(setMarkdown, markdownSourceFromEditor) } } ) return { viewMode, + markdownSourceFromEditor, headMarkdown } }, diff --git a/src/ui/MDXEditor.tsx b/src/ui/MDXEditor.tsx index a3950d9e..dd3a0b00 100644 --- a/src/ui/MDXEditor.tsx +++ b/src/ui/MDXEditor.tsx @@ -60,6 +60,8 @@ import { ImagesPlugin } from './ImagesPlugin' export interface MDXEditorProps { /** * The markdown content to be edited. + * Notice: this is the initial value of the editor. + * If you want to change the value of the editor, use the `setMarkdown` method. */ markdown: string /** @@ -264,7 +266,15 @@ export const defaultMdxOptionValues: DefaultMdxOptionValues = { * ``` */ export interface MDXEditorMethods { + /** + * gets the current markdown value + */ getMarkdown: () => string + + /** + * Updates the markdown value + */ + setMarkdown: (value: string) => void } /** @@ -375,6 +385,7 @@ export const MDXEditor = React.forwardRef( const MDXMethods: React.FC<{ mdxRef: React.ForwardedRef }> = ({ mdxRef }) => { const [markdownSource] = useEmitterValues('markdownSource') + const setMarkdown = usePublisher('setMarkdown') React.useImperativeHandle( mdxRef, @@ -382,10 +393,11 @@ const MDXMethods: React.FC<{ mdxRef: React.ForwardedRef }> = ( return { getMarkdown: () => { return markdownSource - } + }, + setMarkdown } }, - [markdownSource] + [markdownSource, setMarkdown] ) return null } diff --git a/src/ui/SourcePlugin.tsx b/src/ui/SourcePlugin.tsx index 45a7857d..b2533a62 100644 --- a/src/ui/SourcePlugin.tsx +++ b/src/ui/SourcePlugin.tsx @@ -44,8 +44,8 @@ export const ViewModeToggler: React.FC = ({ children }) => { } export const SourceEditor = () => { - const [markdown] = useEmitterValues('markdownSource') - const updateMarkdown = usePublisher('markdownSource') + const [markdown] = useEmitterValues('markdownSourceFromEditor') + const updateMarkdown = usePublisher('markdownSourceFromEditor') const codeMirrorRef = React.useRef(null) return (