Skip to content

Commit

Permalink
fix: Next.js 14.2
Browse files Browse the repository at this point in the history
Fixes #419
Fixes #lexical-issue/issues/1
  • Loading branch information
petyosi committed Apr 15, 2024
1 parent 76634c8 commit c533de7
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 49 deletions.
31 changes: 9 additions & 22 deletions src/MDXEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCellValues, usePublisher, useRealm } from '@mdxeditor/gurx'
import { useCellValue, useCellValues, usePublisher, useRealm } from '@mdxeditor/gurx'
import React from 'react'
import { RealmPlugin, RealmWithPlugins } from './RealmWithPlugins'
import {
Expand All @@ -8,20 +8,16 @@ import {
corePlugin,
editorRootElementRef$,
editorWrappers$,
initialRootEditorState$,
insertMarkdown$,
markdown$,
markdownSourceEditorValue$,
placeholder$,
readOnly$,
rootEditor$,
setMarkdown$,
topAreaChildren$,
usedLexicalNodes$,
viewMode$
} from './plugins/core'

import { LexicalComposer } from '@lexical/react/LexicalComposer.js'
import { ContentEditable } from '@lexical/react/LexicalContentEditable.js'
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary.js'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin.js'
Expand All @@ -31,27 +27,18 @@ import { IconKey } from './plugins/core/Icon'
import { lexicalTheme } from './styles/lexicalTheme'
import styles from './styles/ui.module.css'
import { noop } from './utils/fp'
import { createLexicalComposerContext, LexicalComposerContext, LexicalComposerContextType } from '@lexical/react/LexicalComposerContext'
import { LexicalEditor } from 'lexical'

const LexicalProvider: React.FC<{
children: JSX.Element | string | (JSX.Element | string)[]
}> = ({ children }) => {
const [initialRootEditorState, nodes, readOnly] = useCellValues(initialRootEditorState$, usedLexicalNodes$, readOnly$)
return (
<LexicalComposer
initialConfig={{
editable: !readOnly,
editorState: initialRootEditorState,
namespace: 'MDXEditor',
theme: lexicalTheme,
nodes: nodes,
onError: (error: Error) => {
throw error
}
}}
>
{children}
</LexicalComposer>
)
const rootEditor = useCellValue(rootEditor$)!
const composerContextValue = React.useMemo(() => {
return [rootEditor, createLexicalComposerContext(null, lexicalTheme)] as [LexicalEditor, LexicalComposerContextType]
}, [rootEditor])

return <LexicalComposerContext.Provider value={composerContextValue}>{children}</LexicalComposerContext.Provider>
}

const RichTextEditor: React.FC = () => {
Expand Down
10 changes: 10 additions & 0 deletions src/RealmWithPlugins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { tap } from './utils/fp'
export interface RealmPlugin {
init?: (realm: Realm) => void
update?: (realm: Realm) => void
postInit?: (realm: Realm) => void
}

/**
Expand All @@ -21,6 +22,11 @@ export function realmPlugin<Params>(plugin: {
* Called when the MDXEditor component is mounted and the plugin is initialized.
*/
init?: (realm: Realm, params?: Params) => void

/**
* Called after the MDXEditor component is mounted and all plugins are initialized.
*/
postInit?: (realm: Realm, params?: Params) => void
/**
* Called on each re-render. Use this to update the realm with updated property values.
*/
Expand All @@ -29,6 +35,7 @@ export function realmPlugin<Params>(plugin: {
return function (params?: Params) {
return {
init: (realm: Realm) => plugin.init?.(realm, params),
postInit: (realm: Realm) => plugin.postInit?.(realm, params),
update: (realm: Realm) => plugin.update?.(realm, params)
}
}
Expand All @@ -41,6 +48,9 @@ export function RealmWithPlugins({ children, plugins }: { children: React.ReactN
for (const plugin of plugins) {
plugin.init?.(r)
}
for (const plugin of plugins) {
plugin.postInit?.(r)
}
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Expand Down
66 changes: 39 additions & 27 deletions src/plugins/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { realmPlugin } from '../../RealmWithPlugins'
import { InitialEditorStateType } from '@lexical/react/LexicalComposer.js'
import { createEmptyHistoryState } from '@lexical/react/LexicalHistoryPlugin.js'
import { $isHeadingNode, HeadingTagType } from '@lexical/rich-text'
import { $setBlocksType } from '@lexical/selection'
Expand Down Expand Up @@ -29,7 +28,8 @@ import {
SELECTION_CHANGE_COMMAND,
TextFormatType,
TextNode,
createCommand
createCommand,
createEditor
} from 'lexical'
import * as Mdast from 'mdast'

Expand Down Expand Up @@ -68,6 +68,7 @@ import { DirectiveDescriptor } from '../directives'
import { CodeBlockEditorDescriptor } from '../codeblock'
import { Directives } from 'mdast-util-directive'
import { comment, commentFromMarkdown } from '../../mdastUtilHtmlComment'
import { lexicalTheme } from '../../styles/lexicalTheme'
export * from './MdastHTMLNode'
export * from './GenericHTMLNode'
export * from './Icon'
Expand Down Expand Up @@ -636,31 +637,6 @@ function tryImportingMarkdown(r: Realm, node: ImportPoint, markdownValue: string
}
}

// gets bound to the root editor state getter
/** @internal */
export const initialRootEditorState$ = Cell<InitialEditorStateType | null>(null, (r) => {
r.pub(initialRootEditorState$, (theRootEditor) => {
r.pub(rootEditor$, theRootEditor)
r.pub(activeEditor$, theRootEditor)

tryImportingMarkdown(r, $getRoot(), r.getValue(initialMarkdown$))

const autoFocusValue = r.getValue(autoFocus$)
if (autoFocusValue) {
if (autoFocusValue === true) {
// Default 'on' state
setTimeout(() => theRootEditor.focus(noop, { defaultSelection: 'rootStart' }))
return
}
setTimeout(() =>
theRootEditor.focus(noop, {
defaultSelection: autoFocusValue.defaultSelection ?? 'rootStart'
})
)
}
})
})

/** @internal */
export const composerChildren$ = Cell<React.ComponentType[]>([])

Expand Down Expand Up @@ -901,6 +877,42 @@ export const corePlugin = realmPlugin<{
}
},

postInit(r, params) {
const newEditor = createEditor({
editable: params?.readOnly !== true,
namespace: 'MDXEditor',
nodes: r.getValue(usedLexicalNodes$),
onError: (error) => {
throw error
},
theme: lexicalTheme
})

newEditor.update(() => {
const markdown = params?.initialMarkdown.trim()
if (markdown) {
tryImportingMarkdown(r, $getRoot(), markdown)
}

const autoFocusValue = params?.autoFocus
if (autoFocusValue) {
if (autoFocusValue === true) {
// Default 'on' state
setTimeout(() => newEditor.focus(noop, { defaultSelection: 'rootStart' }))
return
}
setTimeout(() =>
newEditor.focus(noop, {
defaultSelection: autoFocusValue.defaultSelection ?? 'rootStart'
})
)
}
})

r.pub(rootEditor$, newEditor)
r.pub(activeEditor$, newEditor)
},

update(realm, params) {
realm.pubIn({
[contentEditableClassName$]: params?.contentEditableClassName,
Expand Down

0 comments on commit c533de7

Please sign in to comment.