Skip to content

Commit 7ab156e

Browse files
authored
feat(richtext-lexical)!: finalize ClientFeature interface (#6191)
**BREAKING:** If you have own, custom lexical features, there will be a bunch of breaking API changes for you. The saved JSON data is not affected. - `floatingSelectToolbar` has been changed to `toolbarInline` - `slashMenu.dynamicOptions `and `slashMenu.options` have been changed to `slashMenu.groups` and `slashMenu.dynamicGroups` - `toolbarFixed.sections` is now `toolbarFixed.groups` - Slash menu group `options` and toolbar group `entries` have both been renamed to `items` - Toolbar group item `onClick` has been renamed to `onSelect` to match slash menu properties - slashMenu item `onSelect` is no longer auto-wrapped inside an `editor.update`. If you perform editor updates in them, you have to wrap it inside an `editor.update` callback yourself. Within our own features this extra control has removed a good amount of unnecessary, nested `editor.update` calls, which is good - Slash menu items are no longer initialized using the `new` keyword, as they are now types and no longer classes. You can convert them to an object and add the `key` property as an object property instead of an argument to the previous SlashMenuItem constructor - CSS classnames for slash menu and toolbars, as well as their items, have changed - `CheckListFeature` is now exported as and has been renamed to `ChecklistFeature` For guidance on migration, check out how we migrated our own features in this PR's diff: https://github.com/payloadcms/payload/pull/6191/files
1 parent f2d4156 commit 7ab156e

File tree

78 files changed

+942
-883
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+942
-883
lines changed

packages/richtext-lexical/src/exports/components.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ export { RichTextCell } from '../cell/index.js'
22
export { RichTextField } from '../field/index.js'
33

44
export { defaultEditorLexicalConfig } from '../field/lexical/config/client/default.js'
5-
export { ToolbarButton } from '../field/lexical/plugins/FloatingSelectToolbar/ToolbarButton/index.js'
6-
export { ToolbarDropdown } from '../field/lexical/plugins/FloatingSelectToolbar/ToolbarDropdown/index.js'
5+
export { ToolbarButton } from '../field/lexical/plugins/toolbars/inline/ToolbarButton/index.js'
6+
export { ToolbarDropdown } from '../field/lexical/plugins/toolbars/inline/ToolbarDropdown/index.js'

packages/richtext-lexical/src/field/features/align/feature.client.tsx

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,58 +9,52 @@ import { AlignJustifyIcon } from '../../lexical/ui/icons/AlignJustify/index.js'
99
import { AlignLeftIcon } from '../../lexical/ui/icons/AlignLeft/index.js'
1010
import { AlignRightIcon } from '../../lexical/ui/icons/AlignRight/index.js'
1111
import { createClientComponent } from '../createClientComponent.js'
12-
import { AlignDropdownSectionWithEntries } from './floatingSelectToolbarAlignDropdownSection.js'
12+
import { alignGroupWithItems } from './inlineToolbarAlignGroup.js'
1313

1414
const AlignFeatureClient: FeatureProviderProviderClient<undefined> = (props) => {
1515
return {
1616
clientFeatureProps: props,
1717
feature: () => ({
1818
clientFeatureProps: props,
19-
floatingSelectToolbar: {
20-
sections: [
21-
AlignDropdownSectionWithEntries([
19+
toolbarInline: {
20+
groups: [
21+
alignGroupWithItems([
2222
{
2323
ChildComponent: AlignLeftIcon,
2424
isActive: () => false,
25-
key: 'align-left',
25+
key: 'alignLeft',
2626
label: `Align Left`,
27-
onClick: ({ editor }) => {
27+
onSelect: ({ editor }) => {
2828
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'left')
2929
},
3030
order: 1,
3131
},
32-
]),
33-
AlignDropdownSectionWithEntries([
3432
{
3533
ChildComponent: AlignCenterIcon,
3634
isActive: () => false,
37-
key: 'align-center',
35+
key: 'alignCenter',
3836
label: `Align Center`,
39-
onClick: ({ editor }) => {
37+
onSelect: ({ editor }) => {
4038
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'center')
4139
},
4240
order: 2,
4341
},
44-
]),
45-
AlignDropdownSectionWithEntries([
4642
{
4743
ChildComponent: AlignRightIcon,
4844
isActive: () => false,
49-
key: 'align-right',
45+
key: 'alignRight',
5046
label: `Align Right`,
51-
onClick: ({ editor }) => {
47+
onSelect: ({ editor }) => {
5248
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'right')
5349
},
5450
order: 3,
5551
},
56-
]),
57-
AlignDropdownSectionWithEntries([
5852
{
5953
ChildComponent: AlignJustifyIcon,
6054
isActive: () => false,
61-
key: 'align-justify',
55+
key: 'alignJustify',
6256
label: `Align Justify`,
63-
onClick: ({ editor }) => {
57+
onSelect: ({ editor }) => {
6458
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'justify')
6559
},
6660
order: 4,

packages/richtext-lexical/src/field/features/align/floatingSelectToolbarAlignDropdownSection.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type {
2+
InlineToolbarGroup,
3+
InlineToolbarGroupItem,
4+
} from '../../lexical/plugins/toolbars/inline/types.js'
5+
6+
import { AlignLeftIcon } from '../../lexical/ui/icons/AlignLeft/index.js'
7+
8+
export const alignGroupWithItems = (items: InlineToolbarGroupItem[]): InlineToolbarGroup => {
9+
return {
10+
type: 'dropdown',
11+
ChildComponent: AlignLeftIcon,
12+
items,
13+
key: 'align',
14+
order: 2,
15+
}
16+
}

packages/richtext-lexical/src/field/features/blockquote/feature.client.tsx

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,50 @@ import { $getSelection } from 'lexical'
66

77
import type { FeatureProviderProviderClient } from '../types.js'
88

9-
import { SlashMenuOption } from '../../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.js'
109
import { BlockquoteIcon } from '../../lexical/ui/icons/Blockquote/index.js'
11-
import { TextDropdownSectionWithEntries } from '../common/floatingSelectToolbarTextDropdownSection/index.js'
1210
import { createClientComponent } from '../createClientComponent.js'
11+
import { inlineToolbarTextDropdownGroupWithItems } from '../shared/inlineToolbar/textDropdownGroup.js'
1312
import { MarkdownTransformer } from './markdownTransformer.js'
1413

1514
const BlockQuoteFeatureClient: FeatureProviderProviderClient<undefined> = (props) => {
1615
return {
1716
clientFeatureProps: props,
1817
feature: () => ({
1918
clientFeatureProps: props,
20-
floatingSelectToolbar: {
21-
sections: [
22-
TextDropdownSectionWithEntries([
19+
markdownTransformers: [MarkdownTransformer],
20+
nodes: [QuoteNode],
21+
22+
slashMenu: {
23+
groups: [
24+
{
25+
displayName: 'Basic',
26+
items: [
27+
{
28+
Icon: BlockquoteIcon,
29+
displayName: 'Blockquote',
30+
key: 'blockquote',
31+
keywords: ['quote', 'blockquote'],
32+
onSelect: ({ editor }) => {
33+
editor.update(() => {
34+
const selection = $getSelection()
35+
$setBlocksType(selection, () => $createQuoteNode())
36+
})
37+
},
38+
},
39+
],
40+
key: 'basic',
41+
},
42+
],
43+
},
44+
toolbarInline: {
45+
groups: [
46+
inlineToolbarTextDropdownGroupWithItems([
2347
{
2448
ChildComponent: BlockquoteIcon,
2549
isActive: () => false,
2650
key: 'blockquote',
2751
label: `Blockquote`,
28-
onClick: ({ editor }) => {
52+
onSelect: ({ editor }) => {
2953
editor.update(() => {
3054
const selection = $getSelection()
3155
$setBlocksType(selection, () => $createQuoteNode())
@@ -36,28 +60,6 @@ const BlockQuoteFeatureClient: FeatureProviderProviderClient<undefined> = (props
3660
]),
3761
],
3862
},
39-
markdownTransformers: [MarkdownTransformer],
40-
41-
nodes: [QuoteNode],
42-
slashMenu: {
43-
options: [
44-
{
45-
displayName: 'Basic',
46-
key: 'basic',
47-
options: [
48-
new SlashMenuOption(`blockquote`, {
49-
Icon: BlockquoteIcon,
50-
displayName: `Blockquote`,
51-
keywords: ['quote', 'blockquote'],
52-
onSelect: () => {
53-
const selection = $getSelection()
54-
$setBlocksType(selection, () => $createQuoteNode())
55-
},
56-
}),
57-
],
58-
},
59-
],
60-
},
6163
}),
6264
}
6365
}

packages/richtext-lexical/src/field/features/blocks/feature.client.tsx

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { getTranslation } from '@payloadcms/translations'
66

77
import type { FeatureProviderProviderClient } from '../types.js'
88

9-
import { SlashMenuOption } from '../../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.js'
109
import { BlockIcon } from '../../lexical/ui/icons/Block/index.js'
1110
import { createClientComponent } from '../createClientComponent.js'
1211
import { BlockNode } from './nodes/BlocksNode.js'
@@ -30,32 +29,31 @@ const BlocksFeatureClient: FeatureProviderProviderClient<BlocksFeatureClientProp
3029
},
3130
],
3231
slashMenu: {
33-
options: [
32+
groups: [
3433
{
3534
displayName: 'Blocks',
36-
key: 'blocks',
37-
options: [
38-
...props.reducedBlocks.map((block) => {
39-
return new SlashMenuOption('block-' + block.slug, {
40-
Icon: BlockIcon,
41-
displayName: ({ i18n }) => {
42-
if (!block.labels.singular) {
43-
return block.slug
44-
}
35+
items: props.reducedBlocks.map((block) => {
36+
return {
37+
Icon: BlockIcon,
38+
displayName: ({ i18n }) => {
39+
if (!block.labels.singular) {
40+
return block.slug
41+
}
4542

46-
return getTranslation(block.labels.singular, i18n)
47-
},
48-
keywords: ['block', 'blocks', block.slug],
49-
onSelect: ({ editor }) => {
50-
editor.dispatchCommand(INSERT_BLOCK_COMMAND, {
51-
id: null,
52-
blockName: '',
53-
blockType: block.slug,
54-
})
55-
},
56-
})
57-
}),
58-
],
43+
return getTranslation(block.labels.singular, i18n)
44+
},
45+
key: 'block-' + block.slug,
46+
keywords: ['block', 'blocks', block.slug],
47+
onSelect: ({ editor }) => {
48+
editor.dispatchCommand(INSERT_BLOCK_COMMAND, {
49+
id: null,
50+
blockName: '',
51+
blockType: block.slug,
52+
})
53+
},
54+
}
55+
}),
56+
key: 'blocks',
5957
},
6058
],
6159
},

packages/richtext-lexical/src/field/features/common/floatingSelectToolbarFeaturesButtonsSection/index.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

packages/richtext-lexical/src/field/features/common/floatingSelectToolbarTextDropdownSection/index.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.
File renamed without changes.

packages/richtext-lexical/src/field/features/debug/testrecorder/feature.server.ts renamed to packages/richtext-lexical/src/field/features/debug/testRecorder/feature.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const TestRecorderFeature: FeatureProviderProviderServer<undefined, undef
1010
serverFeatureProps: props,
1111
}
1212
},
13-
key: 'testrecorder',
13+
key: 'testRecorder',
1414
serverFeatureProps: props,
1515
}
1616
}

0 commit comments

Comments
 (0)