chore: merge

This commit is contained in:
James
2024-03-01 14:47:48 -05:00
22 changed files with 356 additions and 263 deletions

View File

@@ -1,6 +1,13 @@
module.exports = {
extends: ['@payloadcms'],
overrides: [
{
files: ['scripts/**'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'no-console': 'off',
},
},
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
@@ -34,5 +41,9 @@ module.exports = {
},
},
],
parserOptions: {
project: ['./tsconfig.json'],
tsconfigRootDir: __dirname,
},
root: true,
}

View File

@@ -124,7 +124,7 @@ export const BlockComponent: React.FC<Props> = (props) => {
const formContent = useMemo(() => {
return (
reducedBlock &&
initialState && (
initialState !== false && (
<FieldPathProvider path="" schemaPath="">
<Form
fields={fieldMap}

View File

@@ -13,6 +13,7 @@ import {
} from '@payloadcms/ui'
import { useFieldPath } from '@payloadcms/ui'
import React, { useCallback, useEffect, useState } from 'react'
import { v4 as uuid } from 'uuid'
import { useEditorConfigContext } from '../../../lexical/config/client/EditorConfigProvider'
import './index.scss'
@@ -74,21 +75,22 @@ export const LinkDrawer: React.FC<Props> = ({ drawerSlug, handleModalSubmit, sta
)
return (
initialState !== false && (
<Drawer className={baseClass} slug={drawerSlug} title={t('fields:editLink') ?? ''}>
<Drawer className={baseClass} slug={drawerSlug} title={t('fields:editLink') ?? ''}>
{initialState !== false && (
<FieldPathProvider path="" schemaPath="">
<Form
fields={Array.isArray(fieldMap) ? fieldMap : []}
initialState={initialState}
onChange={[onChange]}
onSubmit={handleModalSubmit}
uuid={uuid()}
>
<RenderFields fieldMap={Array.isArray(fieldMap) ? fieldMap : []} forceRender />
<FormSubmit>{t('general:submit')}</FormSubmit>
</Form>
</FieldPathProvider>
</Drawer>
)
)}
</Drawer>
)
}

View File

@@ -63,7 +63,7 @@ export const LinkFeature: FeatureProviderProviderServer<LinkFeatureServerProps,
disabledCollections: props.disabledCollections,
enabledCollections: props.enabledCollections,
} as ExclusiveLinkCollectionsProps,
generateSchemaMap: ({ config, props, schemaMap, schemaPath }) => {
generateSchemaMap: ({ config, props }) => {
const i18n = initI18n({ config: config.i18n, context: 'client', translations })
return {

View File

@@ -68,11 +68,11 @@ const RelationshipDrawerComponent: React.FC<Props> = ({ enabledCollectionSlugs }
}, [editor, openDrawer])
const onSelect = useCallback(
({ collectionConfig, docID }) => {
({ collectionSlug, docID }) => {
insertRelationship({
id: docID,
editor,
relationTo: collectionConfig.slug,
relationTo: collectionSlug,
replaceNodeKey,
})
closeDrawer()

View File

@@ -0,0 +1,57 @@
'use client'
import { withMergedProps } from '@payloadcms/ui'
import type { FeatureProviderProviderClient } from '../types'
import type { RelationshipFeatureProps } from './feature.server'
import { SlashMenuOption } from '../../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types'
import { RelationshipIcon } from '../../lexical/ui/icons/Relationship'
import { createClientComponent } from '../createClientComponent'
import { INSERT_RELATIONSHIP_WITH_DRAWER_COMMAND } from './drawer/commands'
import { RelationshipNode } from './nodes/RelationshipNode'
import { RelationshipPlugin } from './plugins'
const RelationshipFeatureClient: FeatureProviderProviderClient<RelationshipFeatureProps> = (
props,
) => {
return {
clientFeatureProps: props,
feature: () => ({
clientFeatureProps: props,
nodes: [RelationshipNode],
plugins: [
{
Component: withMergedProps({
Component: RelationshipPlugin,
toMergeIntoProps: props,
}),
position: 'normal',
},
],
slashMenu: {
options: [
{
displayName: 'Basic',
key: 'basic',
options: [
new SlashMenuOption('relationship', {
Icon: RelationshipIcon,
displayName: 'Relationship',
keywords: ['relationship', 'relation', 'rel'],
onSelect: ({ editor }) => {
// dispatch INSERT_RELATIONSHIP_WITH_DRAWER_COMMAND
editor.dispatchCommand(INSERT_RELATIONSHIP_WITH_DRAWER_COMMAND, {
replace: false,
})
},
}),
],
},
],
},
}),
}
}
export const RelationshipFeatureClientComponent = createClientComponent(RelationshipFeatureClient)

View File

@@ -0,0 +1,51 @@
import type { FeatureProviderProviderServer } from '../types'
import { RelationshipFeatureClientComponent } from './feature.client'
import { RelationshipNode } from './nodes/RelationshipNode'
import { relationshipPopulationPromise } from './populationPromise'
export type RelationshipFeatureProps =
| {
/**
* The collections that should be disabled. Overrides the `enableRichTextRelationship` property in the collection config.
* When this property is set, `enabledCollections` will not be available.
**/
disabledCollections?: string[]
// Ensures that enabledCollections is not available when disabledCollections is set
enabledCollections?: never
}
| {
// Ensures that disabledCollections is not available when enabledCollections is set
disabledCollections?: never
/**
* The collections that should be enabled. Overrides the `enableRichTextRelationship` property in the collection config
* When this property is set, `disabledCollections` will not be available.
**/
enabledCollections?: string[]
}
export const RelationshipFeature: FeatureProviderProviderServer<
RelationshipFeatureProps,
RelationshipFeatureProps
> = (props) => {
return {
feature: () => {
return {
ClientComponent: RelationshipFeatureClientComponent,
clientFeatureProps: props,
nodes: [
{
node: RelationshipNode,
populationPromises: [relationshipPopulationPromise],
// TODO: Add validation similar to upload
},
],
serverFeatureProps: props,
}
},
key: 'relationship',
serverFeatureProps: props,
}
}

View File

@@ -1,88 +0,0 @@
import type { FeatureProvider } from '../types'
import { SlashMenuOption } from '../../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types'
import { INSERT_RELATIONSHIP_WITH_DRAWER_COMMAND } from './drawer/commands'
import { RelationshipNode } from './nodes/RelationshipNode'
import { relationshipPopulationPromise } from './populationPromise'
export type RelationshipFeatureProps =
| {
/**
* The collections that should be disabled. Overrides the `enableRichTextRelationship` property in the collection config.
* When this property is set, `enabledCollections` will not be available.
**/
disabledCollections?: string[]
// Ensures that enabledCollections is not available when disabledCollections is set
enabledCollections?: never
}
| {
// Ensures that disabledCollections is not available when enabledCollections is set
disabledCollections?: never
/**
* The collections that should be enabled. Overrides the `enableRichTextRelationship` property in the collection config
* When this property is set, `disabledCollections` will not be available.
**/
enabledCollections?: string[]
}
export const RelationshipFeature = (props?: RelationshipFeatureProps): FeatureProvider => {
return {
feature: () => {
return {
nodes: [
{
type: RelationshipNode.getType(),
node: RelationshipNode,
populationPromises: [relationshipPopulationPromise],
// TODO: Add validation similar to upload
},
],
plugins: [
{
Component: () =>
// @ts-expect-error-next-line
import('./plugins').then((module) => {
const RelationshipPlugin = module.RelationshipPlugin
return import('@payloadcms/ui').then((module2) =>
module2.withMergedProps({
Component: RelationshipPlugin,
toMergeIntoProps: props,
}),
)
}),
position: 'normal',
},
],
props: props,
slashMenu: {
options: [
{
displayName: 'Basic',
key: 'basic',
options: [
new SlashMenuOption('relationship', {
Icon: () =>
// @ts-expect-error-next-line
import('../../lexical/ui/icons/Relationship').then(
(module) => module.RelationshipIcon,
),
displayName: 'Relationship',
keywords: ['relationship', 'relation', 'rel'],
onSelect: ({ editor }) => {
// dispatch INSERT_RELATIONSHIP_WITH_DRAWER_COMMAND
editor.dispatchCommand(INSERT_RELATIONSHIP_WITH_DRAWER_COMMAND, {
replace: false,
})
},
}),
],
},
],
},
}
},
key: 'relationship',
}
}

View File

@@ -57,7 +57,7 @@ const Component: React.FC<Props> = (props) => {
)
const [DocumentDrawer, DocumentDrawerToggler, { closeDrawer }] = useDocumentDrawer({
id: id,
id,
collectionSlug: relatedCollection.slug,
})
@@ -93,7 +93,7 @@ const Component: React.FC<Props> = (props) => {
</p>
<DocumentDrawerToggler className={`${baseClass}__doc-drawer-toggler`}>
<p className={`${baseClass}__title`}>
{data[relatedCollection?.admin?.useAsTitle || 'id']}
{data ? data[relatedCollection?.admin?.useAsTitle || 'id'] : id}
</p>
</DocumentDrawerToggler>
</div>
@@ -102,7 +102,7 @@ const Component: React.FC<Props> = (props) => {
<Button
buttonStyle="icon-label"
className={`${baseClass}__swapButton`}
disabled={field?.admin?.readOnly}
disabled={field?.readOnly}
el="div"
icon="swap"
onClick={() => {
@@ -116,7 +116,7 @@ const Component: React.FC<Props> = (props) => {
<Button
buttonStyle="icon-label"
className={`${baseClass}__removeButton`}
disabled={field?.admin?.readOnly}
disabled={field?.readOnly}
icon="x"
onClick={(e) => {
e.preventDefault()

View File

@@ -14,7 +14,7 @@ import {
import { useEffect } from 'react'
import React from 'react'
import type { RelationshipFeatureProps } from '../index'
import type { RelationshipFeatureProps } from '../feature.server'
import type { RelationshipData } from '../nodes/RelationshipNode'
import { RelationshipDrawer } from '../drawer'
@@ -24,7 +24,7 @@ export const INSERT_RELATIONSHIP_COMMAND: LexicalCommand<RelationshipData> = cre
'INSERT_RELATIONSHIP_COMMAND',
)
export function RelationshipPlugin(props?: RelationshipFeatureProps): JSX.Element | null {
export function RelationshipPlugin(props?: RelationshipFeatureProps): React.ReactNode {
const [editor] = useLexicalComposerContext()
const { collections } = useConfig()

View File

@@ -6,24 +6,24 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
import { getTranslation } from '@payloadcms/translations'
import {
Drawer,
FieldPathProvider,
Form,
type FormProps,
type FormState,
FormSubmit,
RenderFields,
buildStateFromSchema,
fieldTypes,
useAuth,
getFormState,
useConfig,
useDocumentInfo,
useLocale,
useFieldPath,
useTranslation,
} from '@payloadcms/ui'
import { $getNodeByKey } from 'lexical'
import { sanitizeFields } from 'payload/config'
import { deepCopyObject } from 'payload/utilities'
import React, { useCallback, useEffect, useState } from 'react'
import { v4 as uuid } from 'uuid'
import type { ElementProps } from '..'
import type { UploadFeatureProps } from '../..'
import type { UploadData, UploadNode } from '../../nodes/UploadNode'
import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider'
@@ -46,28 +46,58 @@ export const ExtraFieldsUploadDrawer: React.FC<
} = props
const [editor] = useLexicalComposerContext()
const { editorConfig, field } = useEditorConfigContext()
const { closeModal } = useModal()
const { i18n, t } = useTranslation()
const { code: locale } = useLocale()
const { user } = useAuth()
const { closeModal } = useModal()
const { getDocPreferences } = useDocumentInfo()
const [initialState, setInitialState] = useState({})
const fieldSchemaUnsanitized = (
editorConfig?.resolvedFeatureMap.get('upload')?.props as UploadFeatureProps
)?.collections?.[relatedCollection.slug]?.fields
const { id } = useDocumentInfo()
const { schemaPath } = useFieldPath()
const config = useConfig()
const [initialState, setInitialState] = useState<FormState | false>(false)
const {
field: { richTextComponentMap },
} = useEditorConfigContext()
// Sanitize custom fields here
const validRelationships = config.collections.map((c) => c.slug) || []
const fieldSchema = sanitizeFields({
// TODO: fix this
// @ts-expect-error-next-line
config,
fields: fieldSchemaUnsanitized,
validRelationships,
})
const componentMapRenderedFieldsPath = `feature.upload.fields.${relatedCollection.slug}`
const schemaFieldsPath = `${schemaPath}.feature.upload.${relatedCollection.slug}`
const fieldMap = richTextComponentMap.get(componentMapRenderedFieldsPath) // Field Schema
useEffect(() => {
const awaitInitialState = async () => {
const state = await getFormState({
apiRoute: config.routes.api,
body: {
id,
data: deepCopyObject(fields || {}),
operation: 'update',
schemaPath: schemaFieldsPath,
},
serverURL: config.serverURL,
}) // Form State
setInitialState(state)
}
void awaitInitialState()
}, [config.routes.api, config.serverURL, schemaFieldsPath, id, fields])
const onChange: FormProps['onChange'][0] = useCallback(
async ({ formState: prevFormState }) => {
return await getFormState({
apiRoute: config.routes.api,
body: {
id,
formState: prevFormState,
operation: 'update',
schemaPath: schemaFieldsPath,
},
serverURL: config.serverURL,
})
},
[config.routes.api, config.serverURL, schemaFieldsPath, id],
)
const handleUpdateEditData = useCallback(
(_, data) => {
@@ -88,33 +118,6 @@ export const ExtraFieldsUploadDrawer: React.FC<
[closeModal, editor, drawerSlug, nodeKey],
)
useEffect(() => {
// Sanitize custom fields here
const validRelationships = config.collections.map((c) => c.slug) || []
const fieldSchema = sanitizeFields({
// TODO: fix this
// @ts-expect-error-next-line
config,
fields: fieldSchemaUnsanitized,
validRelationships,
})
const awaitInitialState = async () => {
const preferences = await getDocPreferences()
const state = await buildStateFromSchema({
data: deepCopyObject(fields || {}),
fieldSchema,
locale,
operation: 'update',
preferences,
req,
})
setInitialState(state)
}
void awaitInitialState()
}, [user, locale, t, getDocPreferences, fields, fieldSchemaUnsanitized, config])
return (
<Drawer
slug={drawerSlug}
@@ -122,11 +125,20 @@ export const ExtraFieldsUploadDrawer: React.FC<
label: getTranslation(relatedCollection.labels.singular, i18n),
})}
>
<Form initialState={initialState} onSubmit={handleUpdateEditData}>
[RenderFields]
{/* <RenderFields fieldSchema={fieldSchema} fieldTypes={fieldTypes} readOnly={false} /> */}
<FormSubmit>{t('fields:saveChanges')}</FormSubmit>
</Form>
{initialState !== false && (
<FieldPathProvider path="" schemaPath="">
<Form
fields={fieldMap}
initialState={initialState}
onChange={[onChange]}
onSubmit={handleUpdateEditData}
uuid={uuid()}
>
<RenderFields fieldMap={fieldMap} forceRender readOnly={false} />
<FormSubmit>{t('fields:saveChanges')}</FormSubmit>
</Form>
</FieldPathProvider>
)}
</Drawer>
)
}

View File

@@ -18,7 +18,8 @@ import {
import { $getNodeByKey } from 'lexical'
import React, { useCallback, useReducer, useState } from 'react'
import type { UploadFeatureProps } from '..'
import type { ClientComponentProps } from '../../types'
import type { UploadFeaturePropsClient } from '../feature.client'
import type { UploadData } from '../nodes/UploadNode'
import { useEditorConfigContext } from '../../../lexical/config/client/EditorConfigProvider'
@@ -95,9 +96,10 @@ const Component: React.FC<ElementProps> = (props) => {
[setParams, cacheBust, closeDrawer],
)
const customFields = (
editorConfig?.resolvedFeatureMap?.get('upload')?.props as UploadFeatureProps
)?.collections?.[relatedCollection.slug]?.fields
const hasExtraFields = (
editorConfig?.resolvedFeatureMap?.get('upload')
?.clientFeatureProps as ClientComponentProps<UploadFeaturePropsClient>
).collections?.[relatedCollection.slug]?.hasExtraFields
return (
<div
@@ -111,16 +113,14 @@ const Component: React.FC<ElementProps> = (props) => {
</div>
<div className={`${baseClass}__topRowRightPanel`}>
<div className={`${baseClass}__collectionLabel`}>
{/* TODO: fix this */}
{/* @ts-expect-error-next-line */}
{getTranslation(relatedCollection.labels.singular, i18n)}
</div>
{editor.isEditable() && (
<div className={`${baseClass}__actions`}>
{customFields?.length > 0 && (
{hasExtraFields ? (
<DrawerToggler
className={`${baseClass}__upload-drawer-toggler`}
disabled={field?.admin?.readOnly}
disabled={field?.readOnly}
slug={drawerSlug}
>
<Button
@@ -134,11 +134,11 @@ const Component: React.FC<ElementProps> = (props) => {
tooltip={t('fields:editRelationship')}
/>
</DrawerToggler>
)}
) : null}
<Button
buttonStyle="icon-label"
disabled={field?.admin?.readOnly}
disabled={field?.readOnly}
el="div"
icon="swap"
onClick={() => {
@@ -152,7 +152,7 @@ const Component: React.FC<ElementProps> = (props) => {
<Button
buttonStyle="icon-label"
className={`${baseClass}__removeButton`}
disabled={field?.admin?.readOnly}
disabled={field?.readOnly}
icon="x"
onClick={(e) => {
e.preventDefault()

View File

@@ -77,11 +77,11 @@ const UploadDrawerComponent: React.FC<Props> = ({ enabledCollectionSlugs }) => {
}, [editor, openDrawer])
const onSelect = useCallback(
({ collectionConfig, docID }) => {
({ collectionSlug, docID }) => {
insertUpload({
id: docID,
editor,
relationTo: collectionConfig.slug,
relationTo: collectionSlug,
replaceNodeKey,
})
closeDrawer()

View File

@@ -0,0 +1,56 @@
'use client'
import type { FeatureProviderProviderClient } from '../types'
import { SlashMenuOption } from '../../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types'
import { UploadIcon } from '../../lexical/ui/icons/Upload'
import { createClientComponent } from '../createClientComponent'
import { INSERT_UPLOAD_WITH_DRAWER_COMMAND } from './drawer/commands'
import { UploadNode } from './nodes/UploadNode'
import { UploadPlugin } from './plugin'
export type UploadFeaturePropsClient = {
collections: {
[collection: string]: {
hasExtraFields: boolean
}
}
}
const UploadFeatureClient: FeatureProviderProviderClient<UploadFeaturePropsClient> = (props) => {
return {
clientFeatureProps: props,
feature: () => ({
clientFeatureProps: props,
nodes: [UploadNode],
plugins: [
{
Component: UploadPlugin,
position: 'normal',
},
],
slashMenu: {
options: [
{
displayName: 'Basic',
key: 'basic',
options: [
new SlashMenuOption('upload', {
Icon: UploadIcon,
displayName: 'Upload',
keywords: ['upload', 'image', 'file', 'img', 'picture', 'photo', 'media'],
onSelect: ({ editor }) => {
editor.dispatchCommand(INSERT_UPLOAD_WITH_DRAWER_COMMAND, {
replace: false,
})
},
}),
],
},
],
},
}),
}
}
export const UploadFeatureClientComponent = createClientComponent(UploadFeatureClient)

View File

@@ -3,12 +3,11 @@ import type { Field } from 'payload/types'
import payload from 'payload'
import type { HTMLConverter } from '../converters/html/converter/types'
import type { FeatureProvider } from '../types'
import type { SerializedUploadNode } from './nodes/UploadNode'
import type { FeatureProviderProviderServer } from '../types'
import type { UploadFeaturePropsClient } from './feature.client'
import { SlashMenuOption } from '../../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types'
import { INSERT_UPLOAD_WITH_DRAWER_COMMAND } from './drawer/commands'
import { UploadNode } from './nodes/UploadNode'
import { UploadFeatureClientComponent } from './feature.client'
import { type SerializedUploadNode, UploadNode } from './nodes/UploadNode'
import { uploadPopulationPromiseHOC } from './populationPromise'
import { uploadValidation } from './validate'
@@ -27,13 +26,43 @@ function getAbsoluteURL(url: string): string {
return url?.startsWith('http') ? url : (payload?.config?.serverURL || '') + url
}
export const UploadFeature = (props?: UploadFeatureProps): FeatureProvider => {
export const UploadFeature: FeatureProviderProviderServer<
UploadFeatureProps,
UploadFeaturePropsClient
> = (props) => {
if (!props) {
props = { collections: {} }
}
const clientProps: UploadFeaturePropsClient = { collections: {} }
if (props.collections) {
for (const collection in props.collections) {
clientProps.collections[collection] = {
hasExtraFields: props.collections[collection].fields.length >= 1,
}
}
}
return {
feature: () => {
return {
ClientComponent: UploadFeatureClientComponent,
clientFeatureProps: clientProps,
generateSchemaMap: ({ props }) => {
if (!props?.collections) return {}
const map: {
[key: string]: Field[]
} = {}
for (const collection in props.collections) {
map[collection] = props.collections[collection].fields
}
return map
},
nodes: [
{
type: UploadNode.getType(),
converters: {
html: {
converter: async ({ node }) => {
@@ -96,39 +125,10 @@ export const UploadFeature = (props?: UploadFeatureProps): FeatureProvider => {
validations: [uploadValidation()],
},
],
plugins: [
{
Component: () =>
// @ts-expect-error-next-line
import('./plugin').then((module) => module.UploadPlugin),
position: 'normal',
},
],
props,
slashMenu: {
options: [
{
displayName: 'Basic',
key: 'basic',
options: [
new SlashMenuOption('upload', {
Icon: () =>
// @ts-expect-error-next-line
import('../../lexical/ui/icons/Upload').then((module) => module.UploadIcon),
displayName: 'Upload',
keywords: ['upload', 'image', 'file', 'img', 'picture', 'photo', 'media'],
onSelect: ({ editor }) => {
editor.dispatchCommand(INSERT_UPLOAD_WITH_DRAWER_COMMAND, {
replace: false,
})
},
}),
],
},
],
},
serverFeatureProps: props,
}
},
key: 'upload',
serverFeatureProps: props,
}
}

View File

@@ -1,4 +1,5 @@
import type { UploadFeatureProps } from '.'
import type { UploadFeatureProps } from '@payloadcms/richtext-lexical'
import type { PopulationPromise } from '../types'
import type { SerializedUploadNode } from './nodes/UploadNode'

View File

@@ -7,20 +7,26 @@ import type { SerializedUploadNode } from './nodes/UploadNode'
import { CAN_USE_DOM } from '../../lexical/utils/canUseDOM'
export const uploadValidation = (): NodeValidation<SerializedUploadNode> => {
const uploadValidation: NodeValidation<SerializedUploadNode> = async ({
const uploadValidation: NodeValidation<SerializedUploadNode> = ({
node,
payloadConfig,
validation,
validation: {
options: {
req: {
payload: { config, db },
t,
},
},
},
}) => {
if (!CAN_USE_DOM) {
const idField = payloadConfig.collections
const idField = config.collections
.find(({ slug }) => slug === node.relationTo)
.fields.find((field) => fieldAffectsData(field) && field.name === 'id')
const type = getIDType(idField, validation?.options?.payload?.db?.defaultIDType)
const type = getIDType(idField, db?.defaultIDType)
if (!isValidID(node.value?.id, type)) {
return validation.options.t('validation:validUploadID')
return t('validation:validUploadID')
}
}

View File

@@ -19,8 +19,8 @@ import { CheckListFeature } from '../../../features/lists/checklist/feature.serv
import { OrderedListFeature } from '../../../features/lists/orderedlist/feature.server'
import { UnorderedListFeature } from '../../../features/lists/unorderedlist/feature.server'
import { ParagraphFeature } from '../../../features/paragraph/feature.server'
import { RelationshipFeature } from '../../../features/relationship'
import { UploadFeature } from '../../../features/upload'
import { RelationshipFeature } from '../../../features/relationship/feature.server'
import { UploadFeature } from '../../../features/upload/feature.server'
import { LexicalEditorTheme } from '../../theme/EditorTheme'
import { sanitizeServerEditorConfig } from './sanitize'

View File

@@ -319,7 +319,7 @@ export type {
} from './field/features/migrations/slateToLexical/converter/types'
export { SlateToLexicalFeature } from './field/features/migrations/slateToLexical/feature.server'
export { ParagraphFeature } from './field/features/paragraph/feature.server'
export { RelationshipFeature } from './field/features/relationship'
export { RelationshipFeature } from './field/features/relationship/feature.server'
export {
$createRelationshipNode,
$isRelationshipNode,
@@ -346,9 +346,9 @@ export type {
ServerFeature,
ServerFeatureProviderMap,
} from './field/features/types'
export { UploadFeature } from './field/features/upload'
export { UploadFeature } from './field/features/upload/feature.server'
export type { UploadFeatureProps } from './field/features/upload'
export type { UploadFeatureProps } from './field/features/upload/feature.server'
export type { RawUploadPayload } from './field/features/upload/nodes/UploadNode'

42
pnpm-lock.yaml generated
View File

@@ -193,7 +193,7 @@ importers:
version: 9.1.6
next:
specifier: 14.1.1-canary.26
version: 14.1.1-canary.26(@babel/core@7.24.0)(react-dom@18.2.0)(react@18.2.0)
version: 14.1.1-canary.26(@babel/core@7.24.0)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1)
node-mocks-http:
specifier: ^1.14.1
version: 1.14.1
@@ -13301,45 +13301,6 @@ packages:
- babel-plugin-macros
dev: false
/next@14.1.1-canary.26(@babel/core@7.24.0)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-vHj7hCL9qn8AhRXNEC1ujTO55w3IjckEE1tkmxwyqA3ypTH9PtxSnU6eFfC9C67Xf/Q2C5Btug7Yqvw7pxGkhg==}
engines: {node: '>=18.17.0'}
hasBin: true
peerDependencies:
'@opentelemetry/api': ^1.1.0
react: ^18.2.0
react-dom: ^18.2.0
sass: ^1.3.0
peerDependenciesMeta:
'@opentelemetry/api':
optional: true
sass:
optional: true
dependencies:
'@next/env': 14.1.1-canary.26
'@swc/helpers': 0.5.2
busboy: 1.6.0
caniuse-lite: 1.0.30001591
graceful-fs: 4.2.11
postcss: 8.4.31
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
styled-jsx: 5.1.1(@babel/core@7.24.0)(react@18.2.0)
optionalDependencies:
'@next/swc-darwin-arm64': 14.1.1-canary.26
'@next/swc-darwin-x64': 14.1.1-canary.26
'@next/swc-linux-arm64-gnu': 14.1.1-canary.26
'@next/swc-linux-arm64-musl': 14.1.1-canary.26
'@next/swc-linux-x64-gnu': 14.1.1-canary.26
'@next/swc-linux-x64-musl': 14.1.1-canary.26
'@next/swc-win32-arm64-msvc': 14.1.1-canary.26
'@next/swc-win32-ia32-msvc': 14.1.1-canary.26
'@next/swc-win32-x64-msvc': 14.1.1-canary.26
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
dev: true
/next@14.1.1-canary.26(@babel/core@7.24.0)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1):
resolution: {integrity: sha512-vHj7hCL9qn8AhRXNEC1ujTO55w3IjckEE1tkmxwyqA3ypTH9PtxSnU6eFfC9C67Xf/Q2C5Btug7Yqvw7pxGkhg==}
engines: {node: '>=18.17.0'}
@@ -13378,7 +13339,6 @@ packages:
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
dev: false
/node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}

View File

@@ -5,6 +5,9 @@ import { mediaSlug } from '../Media'
export const postsSlug = 'posts'
export const PostsCollection: CollectionConfig = {
admin: {
useAsTitle: 'text',
},
fields: [
{
name: 'text',

View File

@@ -10,12 +10,14 @@ import {
ItalicFeature,
LinkFeature,
OrderedListFeature,
RelationshipFeature,
StrikethroughFeature,
SubscriptFeature,
SuperscriptFeature,
TreeViewFeature,
UnderlineFeature,
UnorderedListFeature,
UploadFeature,
lexicalEditor,
} from '@payloadcms/richtext-lexical'
import path from 'path'
@@ -95,7 +97,15 @@ export function buildConfigWithDefaults(testConfig?: Partial<Config>): Promise<S
editor: lexicalEditor({
features: [
ParagraphFeature(),
LinkFeature(),
RelationshipFeature(),
LinkFeature({
fields: [
{
name: 'description',
type: 'text',
},
],
}),
CheckListFeature(),
UnorderedListFeature(),
OrderedListFeature(),
@@ -103,6 +113,18 @@ export function buildConfigWithDefaults(testConfig?: Partial<Config>): Promise<S
BlockQuoteFeature(),
BoldFeature(),
ItalicFeature(),
UploadFeature({
collections: {
media: {
fields: [
{
name: 'alt',
type: 'text',
},
],
},
},
}),
UnderlineFeature(),
StrikethroughFeature(),
SubscriptFeature(),