fix(richtext-lexical): prevent extra paragraph when inserting blocks or uploadNodes. Add preemptive selection normalization (#12077)

Fixes #11628

PR #6389 caused bug #11628, which is a regression, as it had already
been fixed in #4441

It is likely that some things have changed because [Lexical had recently
made improvements](https://github.com/facebook/lexical/pull/7046) to
address selection normalization.

Although it wasn't necessary to resolve the issue, I added a
`NormalizeSelectionPlugin` to the editor, which makes selection handling
in the editor more robust.

I'm also adding a new collection to the Lexical test suite, intending it
to be used by default for most tests going forward. I've left an
explanatory comment on the dashboard.

___

Looking at #11628's video, it seems users also want to be able to
prevent the first paragraph from being empty. This makes sense to me, so
I think in another PR we could add a button at the top, just [like we
did at the bottom of the
editor](https://github.com/payloadcms/payload/pull/10530).
This commit is contained in:
Germán Jabloñski
2025-04-29 12:57:46 -03:00
committed by GitHub
parent 9948040ad2
commit 5492542c1a
14 changed files with 313 additions and 53 deletions

View File

@@ -83,6 +83,7 @@ export interface Config {
};
blocks: {};
collections: {
'lexical-fully-featured': LexicalFullyFeatured;
'lexical-fields': LexicalField;
'lexical-migrate-fields': LexicalMigrateField;
'lexical-localized-fields': LexicalLocalizedField;
@@ -101,6 +102,7 @@ export interface Config {
};
collectionsJoins: {};
collectionsSelect: {
'lexical-fully-featured': LexicalFullyFeaturedSelect<false> | LexicalFullyFeaturedSelect<true>;
'lexical-fields': LexicalFieldsSelect<false> | LexicalFieldsSelect<true>;
'lexical-migrate-fields': LexicalMigrateFieldsSelect<false> | LexicalMigrateFieldsSelect<true>;
'lexical-localized-fields': LexicalLocalizedFieldsSelect<false> | LexicalLocalizedFieldsSelect<true>;
@@ -153,6 +155,30 @@ export interface UserAuthOperations {
password: string;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "lexical-fully-featured".
*/
export interface LexicalFullyFeatured {
id: string;
richText?: {
root: {
type: string;
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
} | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "lexical-fields".
@@ -774,6 +800,10 @@ export interface User {
export interface PayloadLockedDocument {
id: string;
document?:
| ({
relationTo: 'lexical-fully-featured';
value: string | LexicalFullyFeatured;
} | null)
| ({
relationTo: 'lexical-fields';
value: string | LexicalField;
@@ -864,6 +894,15 @@ export interface PayloadMigration {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "lexical-fully-featured_select".
*/
export interface LexicalFullyFeaturedSelect<T extends boolean = true> {
richText?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "lexical-fields_select".