Created
September 6, 2025 08:39
-
-
Save koraysels/f13a677f7d98126b776bdb7e9462c51b to your computer and use it in GitHub Desktop.
content block lexical psyloadcms
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { Block, Field } from 'payload' | |
| import { | |
| FixedToolbarFeature, | |
| HeadingFeature, | |
| InlineToolbarFeature, | |
| lexicalEditor, | |
| UploadFeature, | |
| UnorderedListFeature, | |
| OrderedListFeature, | |
| } from '@payloadcms/richtext-lexical' | |
| import { link } from '@/fields/link' | |
| const columnFields: Field[] = [ | |
| { | |
| name: 'size', | |
| type: 'select', | |
| defaultValue: 'oneThird', | |
| options: [ | |
| { | |
| label: 'One Third', | |
| value: 'oneThird', | |
| }, | |
| { | |
| label: 'Half', | |
| value: 'half', | |
| }, | |
| { | |
| label: 'Two Thirds', | |
| value: 'twoThirds', | |
| }, | |
| { | |
| label: 'Full', | |
| value: 'full', | |
| }, | |
| ], | |
| }, | |
| { | |
| name: 'richText', | |
| type: 'richText', | |
| editor: lexicalEditor({ | |
| features: ({ rootFeatures }) => { | |
| return [ | |
| ...rootFeatures, | |
| HeadingFeature({ enabledHeadingSizes: ['h2', 'h3', 'h4'] }), | |
| FixedToolbarFeature(), | |
| InlineToolbarFeature(), | |
| UnorderedListFeature(), | |
| OrderedListFeature(), | |
| UploadFeature({ | |
| collections: { | |
| media: { | |
| fields: [ | |
| { | |
| name: 'caption', | |
| type: 'richText', | |
| editor: lexicalEditor(), | |
| }, | |
| ], | |
| }, | |
| }, | |
| }), | |
| ] | |
| }, | |
| }), | |
| label: false, | |
| }, | |
| { | |
| name: 'enableLink', | |
| type: 'checkbox', | |
| }, | |
| link({ | |
| overrides: { | |
| admin: { | |
| condition: (_data, siblingData) => { | |
| return Boolean(siblingData?.enableLink) | |
| }, | |
| }, | |
| }, | |
| }), | |
| ] | |
| export const Content: Block = { | |
| slug: 'content', | |
| interfaceName: 'ContentBlock', | |
| fields: [ | |
| { | |
| name: 'columns', | |
| type: 'array', | |
| admin: { | |
| initCollapsed: true, | |
| }, | |
| fields: columnFields, | |
| }, | |
| ], | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { CollectionConfig } from 'payload' | |
| import { authenticated } from '../../access/authenticated' | |
| import { authenticatedOrPublished } from '../../access/authenticatedOrPublished' | |
| import { About } from '../../blocks/About/config' | |
| import { Archive } from '../../blocks/ArchiveBlock/config' | |
| import { Button } from '../../blocks/molecules/Button/config' | |
| import { TitleConfig as Title } from '../../blocks/molecules/Title' | |
| import { CallToAction } from '../../blocks/CallToAction/config' | |
| import { Content } from '../../blocks/Content/config' | |
| import { Divider } from '../../blocks/Divider/config' | |
| import { FormBlock } from '../../blocks/Form/config' | |
| import { GridPosts } from '../../blocks/GridPosts/config' | |
| import { MediaBlock } from '../../blocks/MediaBlock/config' | |
| import { hero } from '@/heros/config' | |
| import { slugField } from '@/fields/slug' | |
| import { populatePublishedAt } from '../../hooks/populatePublishedAt' | |
| import { generatePreviewPath } from '../../utilities/generatePreviewPath' | |
| import { revalidateDelete, revalidatePage } from './hooks/revalidatePage' | |
| import { fixIdForLocalizedUpdates } from '../../hooks/fixIdForLocalizedUpdates' | |
| import { cleanupDuplicateIds } from '../../hooks/cleanupDuplicateIds' | |
| import { | |
| MetaDescriptionField, | |
| MetaImageField, | |
| MetaTitleField, | |
| OverviewField, | |
| PreviewField, | |
| } from '@payloadcms/plugin-seo/fields' | |
| export const Pages: CollectionConfig<'pages'> = { | |
| slug: 'pages', | |
| access: { | |
| create: authenticated, | |
| delete: authenticated, | |
| read: authenticatedOrPublished, | |
| update: authenticated, | |
| }, | |
| // This config controls what's populated by default when a page is referenced | |
| // https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property | |
| // Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'pages'> | |
| defaultPopulate: { | |
| title: true, | |
| slug: true, | |
| }, | |
| admin: { | |
| defaultColumns: ['title', 'slug', 'updatedAt'], | |
| livePreview: { | |
| url: ({ data, req }) => { | |
| const path = generatePreviewPath({ | |
| slug: typeof data?.slug === 'string' ? data.slug : '', | |
| collection: 'pages', | |
| req, | |
| }) | |
| return path | |
| }, | |
| }, | |
| preview: (data, { req }) => | |
| generatePreviewPath({ | |
| slug: typeof data?.slug === 'string' ? data.slug : '', | |
| collection: 'pages', | |
| req, | |
| }), | |
| useAsTitle: 'title', | |
| }, | |
| fields: [ | |
| { | |
| name: 'title', | |
| type: 'text', | |
| required: true, | |
| localized: true, | |
| }, | |
| { | |
| type: 'tabs', | |
| tabs: [ | |
| { | |
| fields: [ | |
| { | |
| name: 'layout', | |
| type: 'blocks', | |
| blocks: [Title, Button, CallToAction, Content, About, MediaBlock, Archive, FormBlock, GridPosts, Divider], | |
| localized: true, | |
| admin: { | |
| initCollapsed: true, | |
| }, | |
| }, | |
| ], | |
| label: 'Content', | |
| }, | |
| { | |
| fields: [hero], | |
| label: 'Hero', | |
| }, | |
| { | |
| name: 'meta', | |
| label: 'SEO', | |
| localized: true, | |
| fields: [ | |
| OverviewField({ | |
| titlePath: 'meta.title', | |
| descriptionPath: 'meta.description', | |
| imagePath: 'meta.image', | |
| }), | |
| MetaTitleField({ | |
| hasGenerateFn: true, | |
| }), | |
| MetaImageField({ | |
| relationTo: 'media', | |
| }), | |
| MetaDescriptionField({}), | |
| PreviewField({ | |
| // if the `generateUrl` function is configured | |
| hasGenerateFn: true, | |
| // field paths to match the target field for data | |
| titlePath: 'meta.title', | |
| descriptionPath: 'meta.description', | |
| }), | |
| ], | |
| }, | |
| ], | |
| }, | |
| { | |
| name: 'image', | |
| type: 'upload', | |
| relationTo: 'media', | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| label: 'Featured Image', | |
| }, | |
| { | |
| name: 'subtitle', | |
| type: 'text', | |
| localized: true, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| label: 'Subtitle', | |
| }, | |
| { | |
| name: 'shortDescription', | |
| type: 'textarea', | |
| localized: true, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| label: 'Short Description', | |
| }, | |
| { | |
| name: 'backgroundColor', | |
| type: 'select', | |
| options: [ | |
| { | |
| label: 'Default', | |
| value: 'default', | |
| }, | |
| { | |
| label: 'Purple', | |
| value: 'purple', | |
| }, | |
| { | |
| label: 'Yellow', | |
| value: 'yellow', | |
| }, | |
| { | |
| label: 'Green', | |
| value: 'green', | |
| }, | |
| { | |
| label: 'Mint', | |
| value: 'mint', | |
| }, | |
| { | |
| label: 'Blue', | |
| value: 'blue', | |
| }, | |
| { | |
| label: 'Violet', | |
| value: 'violet', | |
| }, | |
| ], | |
| defaultValue: 'default', | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| label: 'Background Color', | |
| }, | |
| { | |
| name: 'publishedAt', | |
| type: 'date', | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| }, | |
| ...slugField(), | |
| ], | |
| hooks: { | |
| afterChange: [revalidatePage], | |
| beforeChange: [fixIdForLocalizedUpdates, cleanupDuplicateIds, populatePublishedAt], | |
| afterDelete: [revalidateDelete], | |
| }, | |
| versions: { | |
| drafts: { | |
| autosave: false, | |
| schedulePublish: true, | |
| }, | |
| maxPerDoc: 50, | |
| }, | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { CollectionConfig } from 'payload' | |
| import { | |
| BlocksFeature, | |
| FixedToolbarFeature, | |
| HeadingFeature, | |
| HorizontalRuleFeature, | |
| InlineToolbarFeature, | |
| lexicalEditor, | |
| } from '@payloadcms/richtext-lexical' | |
| import { authenticated } from '../../access/authenticated' | |
| import { authenticatedOrPublished } from '../../access/authenticatedOrPublished' | |
| import { Banner } from '../../blocks/Banner/config' | |
| import { Button } from '../../blocks/molecules/Button/config' | |
| import { TitleConfig as Title } from '../../blocks/molecules/Title' | |
| import { Code } from '../../blocks/Code/config' | |
| import { Divider } from '../../blocks/Divider/config' | |
| import { MediaBlock } from '../../blocks/MediaBlock/config' | |
| import { generatePreviewPath } from '../../utilities/generatePreviewPath' | |
| import { populateAuthors } from './hooks/populateAuthors' | |
| import { revalidateDelete, revalidatePost } from './hooks/revalidatePost' | |
| import { fixIdForLocalizedUpdates } from '../../hooks/fixIdForLocalizedUpdates' | |
| import { cleanupDuplicateIds } from '../../hooks/cleanupDuplicateIds' | |
| import { | |
| MetaDescriptionField, | |
| MetaImageField, | |
| MetaTitleField, | |
| OverviewField, | |
| PreviewField, | |
| } from '@payloadcms/plugin-seo/fields' | |
| import { slugField } from '@/fields/slug' | |
| export const Posts: CollectionConfig<'posts'> = { | |
| slug: 'posts', | |
| access: { | |
| create: authenticated, | |
| delete: authenticated, | |
| read: authenticatedOrPublished, | |
| update: authenticated, | |
| }, | |
| // This config controls what's populated by default when a post is referenced | |
| // https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property | |
| // Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'posts'> | |
| defaultPopulate: { | |
| title: true, | |
| slug: true, | |
| categories: true, | |
| image: true, | |
| meta: { | |
| image: true, | |
| description: true, | |
| }, | |
| }, | |
| admin: { | |
| defaultColumns: ['title', 'slug', 'updatedAt'], | |
| livePreview: { | |
| url: ({ data, req }) => { | |
| const path = generatePreviewPath({ | |
| slug: typeof data?.slug === 'string' ? data.slug : '', | |
| collection: 'posts', | |
| req, | |
| }) | |
| return path | |
| }, | |
| }, | |
| preview: (data, { req }) => | |
| generatePreviewPath({ | |
| slug: typeof data?.slug === 'string' ? data.slug : '', | |
| collection: 'posts', | |
| req, | |
| }), | |
| useAsTitle: 'title', | |
| }, | |
| fields: [ | |
| { | |
| name: 'title', | |
| type: 'text', | |
| required: true, | |
| localized: true, | |
| }, | |
| { | |
| type: 'tabs', | |
| tabs: [ | |
| { | |
| fields: [ | |
| { | |
| name: 'content', | |
| type: 'richText', | |
| localized: true, | |
| editor: lexicalEditor({ | |
| features: ({ rootFeatures }) => { | |
| return [ | |
| ...rootFeatures, | |
| HeadingFeature({ enabledHeadingSizes: ['h1', 'h2', 'h3', 'h4'] }), | |
| BlocksFeature({ blocks: [Banner, Title, Button, Code, Divider, MediaBlock] }), | |
| FixedToolbarFeature(), | |
| InlineToolbarFeature(), | |
| HorizontalRuleFeature(), | |
| ] | |
| }, | |
| }), | |
| label: false, | |
| required: true, | |
| }, | |
| ], | |
| label: 'Content', | |
| }, | |
| { | |
| fields: [ | |
| { | |
| name: 'relatedPosts', | |
| type: 'relationship', | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| filterOptions: ({ id }) => { | |
| return { | |
| id: { | |
| not_in: [id], | |
| }, | |
| } | |
| }, | |
| hasMany: true, | |
| relationTo: 'posts', | |
| }, | |
| { | |
| name: 'categories', | |
| type: 'relationship', | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| hasMany: true, | |
| relationTo: 'categories', | |
| }, | |
| ], | |
| label: 'Meta', | |
| }, | |
| { | |
| name: 'meta', | |
| label: 'SEO', | |
| fields: [ | |
| OverviewField({ | |
| titlePath: 'meta.title', | |
| descriptionPath: 'meta.description', | |
| imagePath: 'meta.image', | |
| }), | |
| MetaTitleField({ | |
| hasGenerateFn: true, | |
| }), | |
| MetaImageField({ | |
| relationTo: 'media', | |
| }), | |
| MetaDescriptionField({}), | |
| PreviewField({ | |
| // if the `generateUrl` function is configured | |
| hasGenerateFn: true, | |
| // field paths to match the target field for data | |
| titlePath: 'meta.title', | |
| descriptionPath: 'meta.description', | |
| }), | |
| ], | |
| }, | |
| ], | |
| }, | |
| { | |
| name: 'image', | |
| type: 'upload', | |
| relationTo: 'media', | |
| required: true, | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| label: 'Featured Image', | |
| }, | |
| { | |
| name: 'publishedAt', | |
| type: 'date', | |
| admin: { | |
| date: { | |
| pickerAppearance: 'dayAndTime', | |
| }, | |
| position: 'sidebar', | |
| }, | |
| hooks: { | |
| beforeChange: [ | |
| ({ siblingData, value }) => { | |
| if (siblingData._status === 'published' && !value) { | |
| return new Date() | |
| } | |
| return value | |
| }, | |
| ], | |
| }, | |
| }, | |
| { | |
| name: 'authors', | |
| type: 'relationship', | |
| admin: { | |
| position: 'sidebar', | |
| }, | |
| hasMany: true, | |
| relationTo: 'users', | |
| }, | |
| // This field is only used to populate the user data via the `populateAuthors` hook | |
| // This is because the `user` collection has access control locked to protect user privacy | |
| // GraphQL will also not return mutated user data that differs from the underlying schema | |
| { | |
| name: 'populatedAuthors', | |
| type: 'array', | |
| access: { | |
| update: () => false, | |
| }, | |
| admin: { | |
| disabled: true, | |
| readOnly: true, | |
| }, | |
| fields: [ | |
| { | |
| name: 'id', | |
| type: 'text', | |
| }, | |
| { | |
| name: 'name', | |
| type: 'text', | |
| }, | |
| ], | |
| }, | |
| ...slugField(), | |
| ], | |
| hooks: { | |
| afterChange: [revalidatePost], | |
| beforeChange: [fixIdForLocalizedUpdates, cleanupDuplicateIds], | |
| afterRead: [populateAuthors], | |
| afterDelete: [revalidateDelete], | |
| }, | |
| versions: { | |
| drafts: { | |
| autosave: false, | |
| schedulePublish: true, | |
| }, | |
| maxPerDoc: 50, | |
| }, | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment