Files
Alessio Gravili c337e12896 refactor(richtext-lexical): upgrade lexical to 0.50.0 (3.x) (#18148)
Upgrades `lexical` and every installed `@lexical/*` package from
`0.41.0` to `0.50.0` for Payload 3.x. Updates the dependency pins,
lockfile, and `lexicalTargetVersion`.

Also exposes the 15 React entry points added on main in
[#17554](https://github.com/payloadcms/payload/pull/17554) through
`@payloadcms/richtext-lexical/lexical/react/*`, so custom features can
use these APIs through Payload.

## Breaking changes

**No application changes or data migration are needed when using
Payload's built-in rich text features.**

If you maintain custom rich text features, check that they still compile
and that custom content loads, copies, and pastes correctly. Lexical
removed some older APIs, tightened TypeScript types, and changed how
custom nodes are loaded and copied. Tests that inspect the editor's HTML
may also need updated selectors or snapshots because Lexical adds some
internal markup.

**Do not install `lexical` or `@lexical/*` yourself for use with
Payload.** Remove any direct dependencies you added for the editor and
use Payload's re-exports from `@payloadcms/richtext-lexical/lexical` and
`@payloadcms/richtext-lexical/lexical/*`. Payload supplies the matching
versions; mixing versions can break the editor. This is the existing
[custom feature
requirement](https://payloadcms.com/docs/rich-text/custom-features).

The 3.x Markdown implementation and converter defaults are preserved.
This does not backport the v4 Markdown API changes.

## Breaking changes and Payload migrations

Reviewed
[0.42.0](https://github.com/facebook/lexical/releases/tag/v0.42.0),
[0.43.0](https://github.com/facebook/lexical/releases/tag/v0.43.0),
[0.44.0](https://github.com/facebook/lexical/releases/tag/v0.44.0),
[0.45.0](https://github.com/facebook/lexical/releases/tag/v0.45.0),
[0.46.0](https://github.com/facebook/lexical/releases/tag/v0.46.0),
[0.47.0](https://github.com/facebook/lexical/releases/tag/v0.47.0),
[0.48.0](https://github.com/facebook/lexical/releases/tag/v0.48.0),
[0.49.0](https://github.com/facebook/lexical/releases/tag/v0.49.0),
[0.50.0](https://github.com/facebook/lexical/releases/tag/v0.50.0).
Listed below are breaking API/type changes and behavior changes
explicitly identified as breaking in the release notes. Deprecations and
routine bug fixes are omitted. **Yes** means we had to change Payload
code; **No** means no Payload migration was required.

| Release | Breaking change | Required migration in Payload | Changes
made |
| ------- |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| ----------------------------- |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
| 0.42 | [Experimental `hasFitNestedTables` moves out of the table
package into the
playground](https://github.com/facebook/lexical/pull/8210). | No | - |
| 0.42 | [The deprecated context-menu plugin is
removed](https://github.com/facebook/lexical/pull/8199). | Yes | Removed
the invalid `LexicalContextMenuPlugin` proxy and package export. Custom
consumers must use
`@payloadcms/richtext-lexical/lexical/react/LexicalNodeContextMenuPlugin`
and adapt to its node-context-menu API. |
| 0.43 | [Nested editors delegate asynchronously to their
parent](https://github.com/facebook/lexical/pull/8308), restoring the
behavior from before 0.42.0. | No | - |
| 0.45 | [`$getReconciledDirection` now inherits direction through
shadow-root nodes](https://github.com/facebook/lexical/pull/8479). | No
| - |
| 0.45 | [Backspace at the start of a non-empty block preserves the
current block type and
formatting](https://github.com/facebook/lexical/pull/8493). | No | - |
| 0.45 | [Moving nodes between parents adjusts selection
offsets](https://github.com/facebook/lexical/pull/8501). | No | - |
| 0.45 | [Markdown shortcuts can trigger when IME composition
commits](https://github.com/facebook/lexical/pull/8503). | No | - |
| 0.45 | [Rich/plain text automatically removes empty inline
elements](https://github.com/facebook/lexical/pull/8497). | No | - |
| 0.45 | [Triple-click selection normalization moves from core into
rich/plain text
registration](https://github.com/facebook/lexical/pull/8520). Editors
bypassing that registration must add
`NormalizeTripleClickSelectionExtension`. | No | - |
| 0.45 | [`DOMSlot` and the DOM rendering override APIs are
generalized](https://github.com/facebook/lexical/pull/8519); playground
`AutocompleteNode` is replaced by `VisibleLineBreakExtension`. | No | -
|
| 0.46 | [`static importJSON` widens its parameter to
`SerializedLexicalNode & Record<string,
unknown>`](https://github.com/payloadcms/payload/pull/17554). Overrides
using serialized interfaces can fail TypeScript checks. | No | - |
| 0.46 | [Node lookups and traversal no longer infer unchecked subclass
types](https://github.com/facebook/lexical/pull/8661). Explicit
unchecked traversal generics are deprecated. | Yes | Removed the upload
drawer’s assumption that a node lookup returns `UploadNode`. Added
`$isUploadNode` before reading or updating upload data. |
| 0.46 | [DOM lookups of the editor root return `RootNode` instead of
`null`](https://github.com/facebook/lexical/pull/8588).
Selection-capture handling is also generalized beyond decorators. | No |
- |
| 0.46 | [`insertNodes` preserves leading line breaks, and managed line
breaks receive a DOM
marker](https://github.com/facebook/lexical/pull/8615). | No | - |
| 0.46 | [Experimental DOM-import rules register through node
extensions](https://github.com/facebook/lexical/pull/8662); the separate
per-package import extensions become deprecated aliases. | No | - |
| 0.46 | [Experimental named slots change the Yjs sync
signature](https://github.com/facebook/lexical/pull/8603):
`syncLexicalUpdateToYjsV2__EXPERIMENTAL` gains a `dirtyLeaves`
parameter. | No | - |
| 0.46 | [Copying an element through `NodeSelection` includes its
children](https://github.com/facebook/lexical/pull/8603), instead of
copying an empty shell. | No | - |
| 0.46 | [Previously deprecated exports are
removed](https://github.com/facebook/lexical/pull/8704): `toggleLink`,
`insertList`, `removeList`, and ContentEditable’s `Props` alias.
Replacements are `$toggleLink`, `$insertList`, `$removeList`, and
`ContentEditableProps`. | No | - |
| 0.47 | [React 17 support is
removed](https://github.com/facebook/lexical/pull/8782); React 18 or
later is required. | No | - |
| 0.47 | [Segmented text temporarily switches to normal mode during IME
composition while keeping its
DOM](https://github.com/facebook/lexical/pull/8784). Subclasses must
tolerate that temporary mode. | No | - |
| 0.49 | [Built-in nodes adopt
`$config()`](https://github.com/facebook/lexical/pull/8640). Direct
static `importJSON`, `importDOM`, `clone`, and `transform`
implementations change; `__type` becomes readonly and automatic node
construction needs zero-argument defaults. Custom static implementations
remain supported. | No | - |
| 0.49 | [`LexicalCommand<T>` checks its payload type more
strictly](https://github.com/facebook/lexical/pull/8877).
`LexicalCommand<unknown>` is no longer a safe catch-all. | Yes | Focus
and blur commands were incorrectly registered with `MouseEvent`. Removed
the explicit types so Lexical infers `FocusEvent`. |
| 0.50 | [Named-slot values cannot be replaced with
`LexicalNode.replace()`](https://github.com/facebook/lexical/pull/8938).
Block converters also [skip slot
values](https://github.com/facebook/lexical/pull/8905). | No | - |
| 0.50 | [Lexical JSON clipboard copying checks
`excludeFromCopy('clone')`, not
`'html'`](https://github.com/facebook/lexical/pull/8995). | No | - |

Also updated the copied table action menu for merged-cell bounds, header
toggles, and merge/unmerge selection, and fixed the upload alignment
test’s image selector. Formatting and diff checks pass for the upload
selector fix.

Verified all 15 new entry points through source and published export
maps with runtime imports and TypeScript checks. ESLint and formatting
checks pass.

## Previous Lexical upgrades

- [#15760](https://github.com/payloadcms/payload/pull/15760) — 0.35.0 →
0.41.0
- [#13715](https://github.com/payloadcms/payload/pull/13715) — 0.34.0 →
0.35.0
- [#13622](https://github.com/payloadcms/payload/pull/13622) — 0.28.0 →
0.34.0
2026-09-11 16:01:50 -04:00
..
2025-12-19 16:07:14 -05:00
2026-04-14 09:27:46 -07:00
2025-07-18 06:48:27 -04:00
2026-07-01 13:42:19 -07:00