Skip to content

Commit 35df899

Browse files
authored
fix(richtext-lexical): various issues for lexical sub-fields due to incorrectly generated client field schema map (#10276)
Fixes #9905, #9660 Single lexical fields were represented file in the schema map (`path => field`). In the client schema map however, they were incorrectly represented like this: `path => { fields: [field] } `
1 parent 5188a9b commit 35df899

File tree

6 files changed

+105
-4
lines changed

6 files changed

+105
-4
lines changed

packages/richtext-lexical/src/field/rscEntry.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export const RscEntryLexicalField: React.FC<
3030
const path = args.path ?? (args.clientField as RichTextFieldClient).name
3131
const schemaPath = args.schemaPath ?? path
3232

33+
if (!(args?.clientField as RichTextFieldClient)?.name) {
34+
throw new Error('Initialized lexical RSC field without a field name')
35+
}
36+
3337
const { clientFeatures, featureClientSchemaMap } = initLexicalFeatures({
3438
clientFieldSchemaMap: args.clientFieldSchemaMap,
3539
fieldSchemaMap: args.fieldSchemaMap,

packages/ui/src/utilities/buildClientFieldSchemaMap/traverseFields.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
type ClientField,
66
type ClientFieldSchemaMap,
77
createClientFields,
8+
type Field,
89
type FieldSchemaMap,
910
type Payload,
1011
} from 'payload'
@@ -108,16 +109,25 @@ export const traverseFields = ({
108109

109110
// Now loop through them, convert each entry to a client field and add it to the client schema map
110111
for (const [path, subField] of richTextFieldSchemaMap.entries()) {
112+
// check if fields is the only key in the subField object
113+
const isFieldsOnly = Object.keys(subField).length === 1 && 'fields' in subField
114+
111115
const clientFields = createClientFields({
112116
defaultIDType: payload.config.db.defaultIDType,
113117
disableAddingID: true,
114-
fields: 'fields' in subField ? subField.fields : [subField],
118+
fields: isFieldsOnly ? subField.fields : [subField as Field],
115119
i18n,
116120
importMap: payload.importMap,
117121
})
118-
clientSchemaMap.set(path, {
119-
fields: clientFields,
120-
})
122+
123+
clientSchemaMap.set(
124+
path,
125+
isFieldsOnly
126+
? {
127+
fields: clientFields,
128+
}
129+
: clientFields[0],
130+
)
121131
}
122132
break
123133
}

test/fields/collections/Lexical/e2e/blocks/e2e.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,5 +1174,25 @@ describe('lexicalBlocks', () => {
11741174
expect(height2).toBe(74)
11751175
}).toPass()
11761176
})
1177+
1178+
test('ensure nested lexical field displays field label and description', async () => {
1179+
// Previously, we had the issue that nested lexical fields did not display the field label and description, as
1180+
// their client field configs were generated incorrectly on the server.
1181+
await page.goto('http://localhost:3000/admin/collections/LexicalInBlock?limit=10')
1182+
await page.locator('.cell-id a').first().click()
1183+
await page.waitForURL(`**/collections/LexicalInBlock/**`)
1184+
1185+
await expect(
1186+
page.locator('.lexical-block-blockInLexical .render-fields label.field-label'),
1187+
).toHaveText('My Label*')
1188+
await expect(
1189+
page.locator('.lexical-block-blockInLexical .render-fields .required'),
1190+
).toHaveText('*')
1191+
await expect(
1192+
page.locator(
1193+
'.lexical-block-blockInLexical .render-fields .field-description-lexicalInBlock',
1194+
),
1195+
).toHaveText('Some Description')
1196+
})
11771197
})
11781198
})

test/fields/collections/LexicalInBlock/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,37 @@
11
import type { CollectionConfig } from 'payload'
22

3+
import { BlocksFeature, lexicalEditor } from '@payloadcms/richtext-lexical'
4+
35
export const LexicalInBlock: CollectionConfig = {
46
slug: 'LexicalInBlock',
57
fields: [
8+
{
9+
name: 'content',
10+
type: 'richText',
11+
editor: lexicalEditor({
12+
features: [
13+
BlocksFeature({
14+
blocks: [
15+
{
16+
slug: 'blockInLexical',
17+
fields: [
18+
{
19+
name: 'lexicalInBlock',
20+
label: 'My Label',
21+
type: 'richText',
22+
required: true,
23+
editor: lexicalEditor(),
24+
admin: {
25+
description: 'Some Description',
26+
},
27+
},
28+
],
29+
},
30+
],
31+
}),
32+
],
33+
}),
34+
},
635
{
736
name: 'blocks',
837
type: 'blocks',

test/fields/payload-types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,21 @@ export interface User {
412412
*/
413413
export interface LexicalInBlock {
414414
id: string;
415+
content?: {
416+
root: {
417+
type: string;
418+
children: {
419+
type: string;
420+
version: number;
421+
[k: string]: unknown;
422+
}[];
423+
direction: ('ltr' | 'rtl') | null;
424+
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
425+
indent: number;
426+
version: number;
427+
};
428+
[k: string]: unknown;
429+
} | null;
415430
blocks?:
416431
| {
417432
lexical?: {
@@ -2041,6 +2056,7 @@ export interface UsersSelect<T extends boolean = true> {
20412056
* via the `definition` "LexicalInBlock_select".
20422057
*/
20432058
export interface LexicalInBlockSelect<T extends boolean = true> {
2059+
content?: T;
20442060
blocks?:
20452061
| T
20462062
| {

test/fields/seed.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,28 @@ export const seed = async (_payload: Payload) => {
481481
await _payload.create({
482482
collection: 'LexicalInBlock',
483483
data: {
484+
content: {
485+
root: {
486+
children: [
487+
{
488+
format: '',
489+
type: 'block',
490+
version: 2,
491+
fields: {
492+
id: '6773773284be8978db7a498d',
493+
lexicalInBlock: textToLexicalJSON({ text: 'text' }),
494+
blockName: '',
495+
blockType: 'blockInLexical',
496+
},
497+
},
498+
],
499+
direction: null,
500+
format: '',
501+
indent: 0,
502+
type: 'root',
503+
version: 1,
504+
},
505+
},
484506
blocks: [
485507
{
486508
blockType: 'lexicalInBlock2',

0 commit comments

Comments
 (0)