diff --git a/packages/richtext-lexical/src/field/RenderLexical/renderLexical.tsx b/packages/richtext-lexical/src/field/RenderLexical/renderLexical.tsx index 5f989c8760..6684519d10 100644 --- a/packages/richtext-lexical/src/field/RenderLexical/renderLexical.tsx +++ b/packages/richtext-lexical/src/field/RenderLexical/renderLexical.tsx @@ -1,6 +1,5 @@ -import type { JSX } from 'react' - import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent' +import { getSchemaMap } from '@payloadcms/ui/utilities/getSchemaMap' import { createClientField, type PayloadRequest, @@ -13,10 +12,16 @@ import { import { lexicalEditor, type LexicalFieldAdminProps, + type LexicalRichTextAdapter, type SanitizedServerEditorConfig, } from '../../index.js' export type RenderLexicalServerFunctionArgs = { + /** + * 'default' or {global|collections}.entitySlug.fieldSchemaPath + * + * @example collections.posts.richText + */ editorTarget: string req: PayloadRequest } @@ -30,15 +35,37 @@ export const _internal_renderLexical: ServerFunction< throw new Error('Unauthorized') } - const editor = lexicalEditor({ - features: ({ defaultFeatures }) => [], - }) + let sanitizedEditor: LexicalRichTextAdapter + + if (editorTarget === 'default') { + sanitizedEditor = await lexicalEditor()({ + config: req.payload.config, + isRoot: false, + parentIsLocalized: false, + }) + } else { + const [entityType, entitySlug, ...fieldPath] = editorTarget.split('.') + + const schemaMap = getSchemaMap({ + collectionSlug: entityType === 'collections' ? entitySlug : undefined, + config: req.payload.config, + globalSlug: entityType === 'globals' ? entitySlug : undefined, + i18n: req.i18n, + }) + + const field = schemaMap.get(`${entitySlug}.${fieldPath.join('.')}`) as RichTextField | undefined + + if (!field?.editor || typeof field.editor === 'function') { + throw new Error(`No editor found for target: ${editorTarget}`) + } + + sanitizedEditor = field.editor as LexicalRichTextAdapter + } + + if (!sanitizedEditor) { + throw new Error(`No editor found for target: ${editorTarget}`) + } - const sanitizedEditor = await editor({ - config: req.payload.config, - isRoot: false, - parentIsLocalized: false, - }) const field: RichTextField = { name: 'richText', type: 'richText', diff --git a/packages/richtext-lexical/src/field/RenderLexical/useRenderEditor.tsx b/packages/richtext-lexical/src/field/RenderLexical/useRenderEditor.tsx index 5e11465ddf..4eada1b6ce 100644 --- a/packages/richtext-lexical/src/field/RenderLexical/useRenderEditor.tsx +++ b/packages/richtext-lexical/src/field/RenderLexical/useRenderEditor.tsx @@ -9,7 +9,7 @@ import type { } from './renderLexical.js' export const useRenderEditor_internal_ = (args: { - editorTarget: string + editorTarget: 'default' | ({} & string) initialState: DefaultTypedEditorState name: string }) => { diff --git a/test/lexical/collections/OnDemand/OnDemand.tsx b/test/lexical/collections/OnDemand/OnDemand.tsx index 6c796cd9f8..7ec3f8502d 100644 --- a/test/lexical/collections/OnDemand/OnDemand.tsx +++ b/test/lexical/collections/OnDemand/OnDemand.tsx @@ -6,7 +6,7 @@ import { useEffect, useRef } from 'react' export const OnDemand: React.FC = () => { const { Component, renderLexical } = useRenderEditor_internal_({ name: 'richText', - editorTarget: 'your-editor-target', + editorTarget: 'default', initialState: {} as any, }) const mounted = useRef(false) diff --git a/test/lexical/collections/OnDemand/OnDemand2.tsx b/test/lexical/collections/OnDemand/OnDemand2.tsx new file mode 100644 index 0000000000..20669c2a1e --- /dev/null +++ b/test/lexical/collections/OnDemand/OnDemand2.tsx @@ -0,0 +1,24 @@ +'use client' + +import { useRenderEditor_internal_ } from '@payloadcms/richtext-lexical/client' +import { useEffect, useRef } from 'react' + +import { lexicalFullyFeaturedSlug } from '../../../lexical/slugs.js' + +export const OnDemand: React.FC = () => { + const { Component, renderLexical } = useRenderEditor_internal_({ + name: 'richText', + editorTarget: `collections.${lexicalFullyFeaturedSlug}.richText`, + initialState: {} as any, + }) + const mounted = useRef(false) + + useEffect(() => { + if (mounted.current) { + return + } + void renderLexical() + mounted.current = true + }, [renderLexical]) + return