feat(richtext-lexical): make decoratorNodes and blocks selectable. Centralize selection and deletion logic (#10735)

- Blocks can now be selected (only inline blocks were possible before).
- Any DecoratorNode that users create will have the necessary logic out
of the box so that they are selected with a click and deleted with
backspace/delete.
- By having the code for selecting and deleting centralized, a lot of
repetitive code was eliminated
- More performant code due to the use of event delegation. There is only
one listener, previously there was one for each decoratorNode.
- Heuristics to exclude scenarios where you don't want to select the
node: if it is inside the DecoratorNode, but is also inside a button,
input, textarea, contentEditable, .react-select, .code-editor or
.no-select-decorator. That last one was added as a means of opt-out.
- Fix #10634

Note: arrow navigation will be introduced in a later PR.



https://github.com/user-attachments/assets/92f91cad-4f70-4f72-a36f-c68afbe33c0d
This commit is contained in:
Germán Jabloñski
2025-01-22 19:28:48 -03:00
committed by GitHub
parent f181f97d4e
commit 4aaef5e63e
17 changed files with 231 additions and 323 deletions

View File

@@ -1,5 +1,7 @@
import type { CollectionConfig } from 'payload'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
export const postsSlug = 'posts'
export const PostsCollection: CollectionConfig = {
@@ -12,6 +14,13 @@ export const PostsCollection: CollectionConfig = {
name: 'title',
type: 'text',
},
{
name: 'content',
type: 'richText',
editor: lexicalEditor({
features: ({ defaultFeatures }) => [...defaultFeatures],
}),
},
],
versions: {
drafts: true,

View File

@@ -70,6 +70,21 @@ export interface UserAuthOperations {
export interface Post {
id: string;
title?: string | null;
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;
_status?: ('draft' | 'published') | null;
@@ -202,6 +217,7 @@ export interface PayloadMigration {
*/
export interface PostsSelect<T extends boolean = true> {
title?: T;
richText?: T;
updatedAt?: T;
createdAt?: T;
_status?: T;
@@ -324,6 +340,23 @@ export interface MenuSelect<T extends boolean = true> {
createdAt?: T;
globalType?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "ContactBlock".
*/
export interface ContactBlock {
/**
* ...
*/
first: string;
/**
* ...
*/
two: string;
id?: string | null;
blockName?: string | null;
blockType: 'contact';
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "auth".