Skip to content

Commit

Permalink
chore(templates): migrate to new richtext component in website templa…
Browse files Browse the repository at this point in the history
…te (#9615)

In addition to requiring fewer files, it supports more nodes. If you
currently initialize a website template and want to use features such as
images or tables, they are not rendered. With this change that happens
automatically.

Credits to @AlessioGr for the [JSX
serializer](#8795).

---------

Co-authored-by: Paul Popus <paul@nouance.io>
  • Loading branch information
GermanJablo and paulpopus authored Dec 5, 2024
1 parent 3d1305d commit 89db8fb
Show file tree
Hide file tree
Showing 18 changed files with 1,907 additions and 5,399 deletions.
6,798 changes: 1,819 additions & 4,979 deletions templates/website/pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion templates/website/src/app/(frontend)/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default async function Post({ params: paramsPromise }: Args) {

<div className="flex flex-col items-center gap-4 pt-8">
<div className="container">
<RichText className="max-w-[48rem] mx-auto" content={post.content} enableGutter={false} />
<RichText className="max-w-[48rem] mx-auto" data={post.content} enableGutter={false} />
{post.relatedPosts && post.relatedPosts.length > 0 && (
<RelatedPosts
className="mt-12 max-w-[52rem] lg:grid lg:grid-cols-subgrid col-start-1 col-span-3 grid-rows-[2fr]"
Expand Down
61 changes: 22 additions & 39 deletions templates/website/src/app/(payload)/admin/importMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,26 @@ import { default as default_1a7510af427896d367a49dbf838d2de6 } from '@/component
import { default as default_8a7ab0eb7ab5c511aba12e68480bfe5e } from '@/components/BeforeLogin'

export const importMap = {
'@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell':
RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
'@payloadcms/richtext-lexical/rsc#RscEntryLexicalField':
RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
'@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient':
InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient':
FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#HeadingFeatureClient':
HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#ParagraphFeatureClient':
ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#UnderlineFeatureClient':
UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#BoldFeatureClient':
BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#ItalicFeatureClient':
ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#LinkFeatureClient':
LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/plugin-seo/client#OverviewComponent':
OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
'@payloadcms/plugin-seo/client#MetaTitleComponent':
MetaTitleComponent_a8a977ebc872c5d5ea7ee689724c0860,
'@payloadcms/plugin-seo/client#MetaImageComponent':
MetaImageComponent_a8a977ebc872c5d5ea7ee689724c0860,
'@payloadcms/plugin-seo/client#MetaDescriptionComponent':
MetaDescriptionComponent_a8a977ebc872c5d5ea7ee689724c0860,
'@payloadcms/plugin-seo/client#PreviewComponent':
PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
'@/fields/slug/SlugComponent#SlugComponent': SlugComponent_92cc057d0a2abb4f6cf0307edf59f986,
'@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient':
HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/richtext-lexical/client#BlocksFeatureClient':
BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
'@payloadcms/plugin-search/client#LinkToDoc': LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634,
'@payloadcms/plugin-search/client#ReindexButton': ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
'@/components/BeforeDashboard#default': default_1a7510af427896d367a49dbf838d2de6,
'@/components/BeforeLogin#default': default_8a7ab0eb7ab5c511aba12e68480bfe5e,
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
"@payloadcms/plugin-seo/client#MetaTitleComponent": MetaTitleComponent_a8a977ebc872c5d5ea7ee689724c0860,
"@payloadcms/plugin-seo/client#MetaImageComponent": MetaImageComponent_a8a977ebc872c5d5ea7ee689724c0860,
"@payloadcms/plugin-seo/client#MetaDescriptionComponent": MetaDescriptionComponent_a8a977ebc872c5d5ea7ee689724c0860,
"@payloadcms/plugin-seo/client#PreviewComponent": PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
"@/fields/slug/SlugComponent#SlugComponent": SlugComponent_92cc057d0a2abb4f6cf0307edf59f986,
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/plugin-search/client#LinkToDoc": LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634,
"@payloadcms/plugin-search/client#ReindexButton": ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
"@/components/BeforeDashboard#default": default_1a7510af427896d367a49dbf838d2de6,
"@/components/BeforeLogin#default": default_8a7ab0eb7ab5c511aba12e68480bfe5e
}
2 changes: 1 addition & 1 deletion templates/website/src/blocks/ArchiveBlock/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const ArchiveBlock: React.FC<
<div className="my-16" id={`block-${id}`}>
{introContent && (
<div className="container mb-16">
<RichText className="ml-0 max-w-[48rem]" content={introContent} enableGutter={false} />
<RichText className="ml-0 max-w-[48rem]" data={introContent} enableGutter={false} />
</div>
)}
<CollectionArchive posts={posts} />
Expand Down
2 changes: 1 addition & 1 deletion templates/website/src/blocks/Banner/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const BannerBlock: React.FC<Props> = ({ className, content, style }) => {
'border-warning bg-warning/30': style === 'warning',
})}
>
<RichText content={content} enableGutter={false} enableProse={false} />
<RichText data={content} enableGutter={false} enableProse={false} />
</div>
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion templates/website/src/blocks/CallToAction/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const CallToActionBlock: React.FC<CTABlockProps> = ({ links, richText })
<div className="container">
<div className="bg-card rounded border-border border p-4 flex flex-col gap-8 md:flex-row md:justify-between md:items-center">
<div className="max-w-[48rem] flex items-center">
{richText && <RichText className="mb-0" content={richText} enableGutter={false} />}
{richText && <RichText className="mb-0" data={richText} enableGutter={false} />}
</div>
<div className="flex flex-col gap-8">
{(links || []).map(({ link }, i) => {
Expand Down
2 changes: 1 addition & 1 deletion templates/website/src/blocks/Content/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const ContentBlock: React.FC<ContentBlockProps> = (props) => {
})}
key={index}
>
{richText && <RichText content={richText} enableGutter={false} />}
{richText && <RichText data={richText} enableGutter={false} />}

{enableLink && <CMSLink {...link} />}
</div>
Expand Down
9 changes: 4 additions & 5 deletions templates/website/src/blocks/Form/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { useCallback, useState } from 'react'
import { useForm, FormProvider } from 'react-hook-form'
import RichText from '@/components/RichText'
import { Button } from '@/components/ui/button'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'

import { buildInitialFormState } from './buildInitialFormState'
import { fields } from './fields'
Expand All @@ -26,9 +27,7 @@ export type FormBlockType = {
blockType?: 'formBlock'
enableIntro: boolean
form: FormType
introContent?: {
[k: string]: unknown
}[]
introContent?: SerializedEditorState
}

export const FormBlock: React.FC<
Expand Down Expand Up @@ -128,12 +127,12 @@ export const FormBlock: React.FC<
return (
<div className="container lg:max-w-[48rem]">
{enableIntro && introContent && !hasSubmitted && (
<RichText className="mb-8 lg:mb-12" content={introContent} enableGutter={false} />
<RichText className="mb-8 lg:mb-12" data={introContent} enableGutter={false} />
)}
<div className="p-4 lg:p-6 border border-border rounded-[0.8rem]">
<FormProvider {...formMethods}>
{!isLoading && hasSubmitted && confirmationType === 'message' && (
<RichText content={confirmationMessage} />
<RichText data={confirmationMessage} />
)}
{isLoading && !hasSubmitted && <p>Loading, please wait...</p>}
{error && <div>{`${error.status || '500'}: ${error.message || ''}`}</div>}
Expand Down
5 changes: 3 additions & 2 deletions templates/website/src/blocks/Form/Message/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import RichText from '@/components/RichText'
import React from 'react'

import { Width } from '../Width'
import { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'

export const Message: React.FC = ({ message }: { message: Record<string, any> }) => {
export const Message: React.FC = ({ message }: { message: SerializedEditorState }) => {
return (
<Width className="my-12" width="100">
{message && <RichText content={message} />}
{message && <RichText data={message} />}
</Width>
)
}
2 changes: 1 addition & 1 deletion templates/website/src/blocks/MediaBlock/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const MediaBlock: React.FC<Props> = (props) => {
captionClassName,
)}
>
<RichText content={caption} enableGutter={false} />
<RichText data={caption} enableGutter={false} />
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/website/src/blocks/RelatedPosts/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const RelatedPosts: React.FC<RelatedPostsProps> = (props) => {

return (
<div className={clsx('container', className)}>
{introContent && <RichText content={introContent} enableGutter={false} />}
{introContent && <RichText data={introContent} enableGutter={false} />}

<div className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8 items-stretch">
{docs?.map((doc, index) => {
Expand Down
72 changes: 47 additions & 25 deletions templates/website/src/components/RichText/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
import { MediaBlock } from '@/blocks/MediaBlock/Component'
import { DefaultNodeTypes, SerializedBlockNode } from '@payloadcms/richtext-lexical'
import { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
import {
JSXConvertersFunction,
RichText as RichTextWithoutBlocks,
} from '@payloadcms/richtext-lexical/react'

import { CodeBlock, CodeBlockProps } from '@/blocks/Code/Component'

import type {
BannerBlock as BannerBlockProps,
CallToActionBlock as CTABlockProps,
MediaBlock as MediaBlockProps,
} from '@/payload-types'
import { BannerBlock } from '@/blocks/Banner/Component'
import { CallToActionBlock } from '@/blocks/CallToAction/Component'
import { cn } from '@/utilities/cn'
import React from 'react'

import { serializeLexical } from './serialize'
type NodeTypes =
| DefaultNodeTypes
| SerializedBlockNode<CTABlockProps | MediaBlockProps | BannerBlockProps | CodeBlockProps>

const jsxConverters: JSXConvertersFunction<NodeTypes> = ({ defaultConverters }) => ({
...defaultConverters,
blocks: {
banner: ({ node }) => <BannerBlock className="col-start-2 mb-4" {...node.fields} />,
mediaBlock: ({ node }) => (
<MediaBlock
className="col-start-1 col-span-3"
imgClassName="m-0"
{...node.fields}
captionClassName="mx-auto max-w-[48rem]"
enableGutter={false}
disableInnerContainer={true}
/>
),
code: ({ node }) => <CodeBlock className="col-start-2" {...node.fields} />,
cta: ({ node }) => <CallToActionBlock {...node.fields} />,
},
})

type Props = {
className?: string
content: Record<string, any>
data: SerializedEditorState
enableGutter?: boolean
enableProse?: boolean
}

const RichText: React.FC<Props> = ({
className,
content,
enableGutter = true,
enableProse = true,
}) => {
if (!content) {
return null
}
} & React.HTMLAttributes<HTMLDivElement>

export default function RichText(props: Props) {
const { className, enableProse = true, enableGutter = true, ...rest } = props
return (
<div
<RichTextWithoutBlocks
converters={jsxConverters}
className={cn(
{
'container ': enableGutter,
Expand All @@ -30,14 +59,7 @@ const RichText: React.FC<Props> = ({
},
className,
)}
>
{content &&
!Array.isArray(content) &&
typeof content === 'object' &&
'root' in content &&
serializeLexical({ nodes: content?.root?.children })}
</div>
{...rest}
/>
)
}

export default RichText
128 changes: 0 additions & 128 deletions templates/website/src/components/RichText/nodeFormat.tsx

This file was deleted.

Loading

0 comments on commit 89db8fb

Please sign in to comment.