BREAKING: requires user to install @payloacms-richtext-slate and specify a `config.editor` property * chore: move slate stuff into packages/richtext-slate * chore: fieldTypes stuff * chore: fix richtext-slate tsconfig * chore: add clean:unix command * chore: fix up things * chore: undo subpath imports being hoisted up * chore: fix incorrect imports * chore: improve AdapterArguments type * chore: remove unused richTextToHTML and stringifyRichText files * fix: core-dev scss imports * chore: fix publishConfig exports for richtext-slate * chore: adjust joi schema for richtext field * chore: various fixes * chore: handle afterRead population in richText adapter * chore: handle more after-read promise stuff * chore: fix joi validation * chore: add richtext adapter to tests * chore: merge adapter props with field props * chore: index.tsx => index.ts * chore: rename `adapter` to `editor` * chore: fix e2e tests not running due to importing a constant from a file (`Tabs`) which imports createSlate. This fails because createSlate imports React components. * chore: remove unnecessary import * chore: improve various typings * chore: improve typings for List view Cell components * feat: richText adapter cell component * chore: add missing types packages for packages/richtext-slate * chore: add new adapter interface properties to joi schema * chore: withMergedProps utility which replaces getSlateCellComponent and getSlateFieldComponent * feat: added config.defaultEditor property which is now required. field.editor is no longer required and overrides config.defaultEditor * docs: mention editor and defaultEditor property in the docs * chore: fix incorrectly formatted JSX in docs files breaking mdx parser * chore: fix various errors * chore: auto-generated pointer files
507 lines
10 KiB
TypeScript
507 lines
10 KiB
TypeScript
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
|
|
|
import { createSlate } from '../../../../packages/richtext-slate/src'
|
|
import { loremIpsum } from './loremIpsum'
|
|
|
|
const RichTextFields: CollectionConfig = {
|
|
slug: 'rich-text-fields',
|
|
admin: {
|
|
useAsTitle: 'title',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'selectHasMany',
|
|
hasMany: true,
|
|
type: 'select',
|
|
admin: {
|
|
description:
|
|
'This select field is rendered here to ensure its options dropdown renders above the rich text toolbar.',
|
|
},
|
|
options: [
|
|
{
|
|
label: 'Value One',
|
|
value: 'one',
|
|
},
|
|
{
|
|
label: 'Value Two',
|
|
value: 'two',
|
|
},
|
|
{
|
|
label: 'Value Three',
|
|
value: 'three',
|
|
},
|
|
{
|
|
label: 'Value Four',
|
|
value: 'four',
|
|
},
|
|
{
|
|
label: 'Value Five',
|
|
value: 'five',
|
|
},
|
|
{
|
|
label: 'Value Six',
|
|
value: 'six',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'richText',
|
|
type: 'richText',
|
|
editor: createSlate({
|
|
admin: {
|
|
elements: [
|
|
'h1',
|
|
'h2',
|
|
'h3',
|
|
'h4',
|
|
'h5',
|
|
'h6',
|
|
'ul',
|
|
'ol',
|
|
'textAlign',
|
|
'indent',
|
|
'link',
|
|
'relationship',
|
|
'upload',
|
|
],
|
|
link: {
|
|
fields: [
|
|
{
|
|
name: 'rel',
|
|
label: 'Rel Attribute',
|
|
type: 'select',
|
|
hasMany: true,
|
|
options: ['noopener', 'noreferrer', 'nofollow'],
|
|
admin: {
|
|
description:
|
|
'The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field.',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
upload: {
|
|
collections: {
|
|
uploads: {
|
|
fields: [
|
|
{
|
|
name: 'caption',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'richTextCustomFields',
|
|
type: 'richText',
|
|
editor: createSlate({
|
|
admin: {
|
|
elements: [
|
|
'h1',
|
|
'h2',
|
|
'h3',
|
|
'h4',
|
|
'h5',
|
|
'h6',
|
|
'ul',
|
|
'ol',
|
|
'indent',
|
|
'link',
|
|
'relationship',
|
|
'upload',
|
|
],
|
|
link: {
|
|
fields: ({ defaultFields }) => {
|
|
return [
|
|
...defaultFields,
|
|
{
|
|
label: 'Custom',
|
|
name: 'customLinkField',
|
|
type: 'text',
|
|
},
|
|
]
|
|
},
|
|
},
|
|
upload: {
|
|
collections: {
|
|
uploads: {
|
|
fields: [
|
|
{
|
|
name: 'caption',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
},
|
|
{
|
|
name: 'richTextReadOnly',
|
|
type: 'richText',
|
|
admin: {
|
|
readOnly: true,
|
|
},
|
|
editor: createSlate({
|
|
admin: {
|
|
elements: [
|
|
'h1',
|
|
'h2',
|
|
'h3',
|
|
'h4',
|
|
'h5',
|
|
'h6',
|
|
'ul',
|
|
'ol',
|
|
'indent',
|
|
'link',
|
|
'relationship',
|
|
'upload',
|
|
],
|
|
link: {
|
|
fields: [
|
|
{
|
|
name: 'rel',
|
|
label: 'Rel Attribute',
|
|
type: 'select',
|
|
hasMany: true,
|
|
options: ['noopener', 'noreferrer', 'nofollow'],
|
|
admin: {
|
|
description:
|
|
'The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field.',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
upload: {
|
|
collections: {
|
|
uploads: {
|
|
fields: [
|
|
{
|
|
name: 'caption',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
},
|
|
{
|
|
name: 'blocks',
|
|
type: 'blocks',
|
|
blocks: [
|
|
{
|
|
slug: 'textBlock',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
slug: 'richTextBlock',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
function generateRichText() {
|
|
return [
|
|
{
|
|
children: [
|
|
{
|
|
text: "Hello, I'm a rich text field.",
|
|
},
|
|
],
|
|
type: 'h1',
|
|
textAlign: 'center',
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'I can do all kinds of fun stuff like ',
|
|
},
|
|
{
|
|
type: 'link',
|
|
url: 'https://payloadcms.com',
|
|
newTab: true,
|
|
children: [
|
|
{
|
|
text: 'render links',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
text: ', ',
|
|
},
|
|
{
|
|
type: 'link',
|
|
linkType: 'internal',
|
|
doc: {
|
|
value: '{{ARRAY_DOC_ID}}',
|
|
relationTo: 'array-fields',
|
|
},
|
|
fields: {},
|
|
children: [
|
|
{
|
|
text: 'link to relationships',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
text: ', and store nested relationship fields:',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: '',
|
|
},
|
|
],
|
|
type: 'relationship',
|
|
value: {
|
|
id: '',
|
|
},
|
|
relationTo: 'text-fields',
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'You can build your own elements, too.',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'ul',
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
text: "It's built with SlateJS",
|
|
},
|
|
],
|
|
type: 'li',
|
|
},
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: 'It stores content as JSON so you can use it wherever you need',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: "It's got a great editing experience for non-technical users",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'And a whole lot more.',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: '',
|
|
},
|
|
],
|
|
type: 'upload',
|
|
value: {
|
|
id: '',
|
|
},
|
|
relationTo: 'uploads',
|
|
fields: {
|
|
caption: [
|
|
...[...Array(4)].map(() => {
|
|
return {
|
|
children: [
|
|
{
|
|
text: loremIpsum,
|
|
},
|
|
],
|
|
}
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: '',
|
|
},
|
|
],
|
|
},
|
|
...[...Array(2)].map(() => {
|
|
return {
|
|
children: [
|
|
{
|
|
text: loremIpsum,
|
|
},
|
|
],
|
|
}
|
|
}),
|
|
]
|
|
}
|
|
|
|
export const richTextBulletsDoc = {
|
|
title: 'Bullets and Indentation',
|
|
richText: [
|
|
{
|
|
type: 'ul',
|
|
children: [
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
text: 'I am semantically connected to my sub-bullets',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'ul',
|
|
children: [
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: 'I am sub-bullets that are semantically connected to the parent bullet',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Normal bullet',
|
|
},
|
|
],
|
|
type: 'li',
|
|
},
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
type: 'ul',
|
|
children: [
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: 'I am the old style of sub-bullet',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: 'Another normal bullet',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
text: 'This text precedes a nested list',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'ul',
|
|
children: [
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: 'I am a sub-bullet',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'li',
|
|
children: [
|
|
{
|
|
text: 'And I am another sub-bullet',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
export const richTextBlocks = [
|
|
{
|
|
blockType: 'textBlock',
|
|
text: 'Regular text',
|
|
},
|
|
{
|
|
blockType: 'richTextBlock',
|
|
text: [
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Rich text',
|
|
},
|
|
],
|
|
type: 'h1',
|
|
},
|
|
],
|
|
},
|
|
]
|
|
export const richTextDoc = {
|
|
title: 'Rich Text',
|
|
selectHasMany: ['one', 'five'],
|
|
richText: generateRichText(),
|
|
richTextReadOnly: generateRichText(),
|
|
richTextCustomFields: generateRichText(),
|
|
blocks: richTextBlocks,
|
|
}
|
|
|
|
export default RichTextFields
|