Skip to content

feat(richtext-lexical): upgrade lexical from 0.35.0 to 0.41.0#15760

Merged
GermanJablo merged 4 commits intomainfrom
feat-upgrade-lexical-0.40.0
Mar 2, 2026
Merged

feat(richtext-lexical): upgrade lexical from 0.35.0 to 0.41.0#15760
GermanJablo merged 4 commits intomainfrom
feat-upgrade-lexical-0.40.0

Conversation

@GermanJablo
Copy link
Copy Markdown
Contributor

@GermanJablo GermanJablo commented Feb 25, 2026

Summary

Upgrades the lexical dependency from 0.35.0 to 0.41.0.

Keeping up with Lexical releases avoids accumulating too large a gap, which makes future upgrades risky and time-consuming. This upgrade also brings in the upstream normalizeMarkdown fix (facebook/lexical#7812), which means we can eventually drop our vendored copy of that function.

If you installed lexical manually, update it to 0.41.0. Installing lexical manually is not recommended, as it may break between updates, and our re-exported versions should be used. See the yellow banner box for details.

If you still encounter richtext-lexical errors, do the following, in this order:

  • Delete node_modules
  • Delete your lockfile (e.g. pnpm-lock.json)
  • Reinstall your dependencies (e.g. pnpm install)

Lexical Breaking Changes

The following Lexical releases contain breaking changes. We recommend reading them if you're using Lexical APIs directly (@payloadcms/richtext-lexical/lexical/*).

  • v0.41.0--lexical-indent-base-value CSS custom property is now only read from the editor root element, not from indented elements. Payload already handles this change internally — no action required.
  • v0.39.0ElementNode JSON serialization: textFormat and textStyle are now only serialized when necessary (when the node has no direct TextNode children). May affect code that reads these properties from serialized data.
  • v0.38.0 — Static transforms from superclasses are now always applied. Table selection handler priorities lowered from CRITICAL to HIGH.
  • v0.36.1DecoratorNode.decorate() return type widened to null | T. Collaboration context changes (not used by Payload).

None of these breaking changes require action from Payload users under normal usage.

Changes

  • Bump all @lexical/* and lexical from 0.35.0 to 0.41.0
  • Update lexicalTargetVersion constant
  • Move --lexical-indent-base-value CSS variable from .LexicalEditorTheme__indent to the .LexicalEditorTheme root selector (v0.41.0 breaking change)
  • Update textFormat test expectations for inline code paragraphs (v0.39.0 serialization change)
  • Update pnpm-lock.yaml

Previous Lexical Upgrades

Bump all @lexical/* and lexical dependencies to 0.40.0 and update
the lexicalTargetVersion constant.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 25, 2026

📦 esbuild Bundle Analysis for payload

This analysis was generated by esbuild-bundle-analyzer. 🤖
This PR introduced no changes to the esbuild bundle! 🙌

type: 'paragraph',
version: 1,
textFormat: 0,
textFormat: 16,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lexical v0.39.0, via facebook/lexical#7971, changed how ElementNode serializes textFormat and textStyle to JSON.
Now, Lexical computes textFormat from the children's format, so a paragraph containing only inline code text (format: 16) will have textFormat: 16 instead of 0. The property is also omitted entirely when it's not needed (e.g., when the element has direct TextNode children that already carry the format).
The inline code rendering is identical; only the serialized metadata on the parent paragraph changed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property is also omitted entirely when it's not needed (e.g., when the element has direct TextNode children that already carry the format)

Isn't this the case here, and we should be able to remove the textFormat property here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The test is asking for it.
It seems the paragraph gets its formatting from its children in cases like this.

Move --lexical-indent-base-value CSS variable from indent class to
editor root element per v0.41.0 breaking change (#8132).
@GermanJablo GermanJablo changed the title feat(richtext-lexical): upgrade lexical from 0.35.0 to 0.40.0 feat(richtext-lexical): upgrade lexical from 0.35.0 to 0.41.0 Feb 25, 2026
@GermanJablo GermanJablo merged commit ba3bd74 into main Mar 2, 2026
152 checks passed
@GermanJablo GermanJablo deleted the feat-upgrade-lexical-0.40.0 branch March 2, 2026 15:38
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 4, 2026

🚀 This is included in version v3.79.0

tadjh added a commit to digitalgroundgame/pragmatic-papers that referenced this pull request Mar 18, 2026
## Context

### BREAKING CHANGES:
The only listed breaking changes are in payload 3.79.0. Two of them.
>- rename widget ComponentPath to Component for consistency
([#15780](payloadcms/payload#15780))
([f7d0d04](payloadcms/payload@f7d0d04)
- Renames `Widget.ComponentPath` to `Widget.Component` and types it as
PayloadComponent`instead of`string`
- This aligns dashboard widgets with every other component reference in
(collections, globals, fields, admin components) - none of them _path_
in the property name, and all of them are typed as `PayloadComponent`
- Enables new [typescript
plugin](payloadcms/payload#15779) to work for
widget paths (the plugin uses `PayloadComponent` contextual type
detection - `string`-typed properties were invisible to it)
> - **ui:** typo in CodeEditor export statement
([#15795](payloadcms/payload#15795))
([c5b2a91](payloadcms/payload@c5b2a91))

>**Lexical Upgrade 0.35.0 → 0.41.0 (richtext-lexical)** — Upgrades the
Lexical rich text editor dependency from v0.35.0 to v0.41.0. Includes
upstream fixes like `normalizeMarkdown`
([facebook/lexical#7812](facebook/lexical#7812)).
All Lexical breaking changes are handled internally by Payload — no
action required for standard usage. If you installed `lexical` manually,
update it to 0.41.0 (though using the re-exported versions from
`@payloadcms/richtext-lexical/lexical/*` is recommended).
[#15760](payloadcms/payload#15760)

### Anaylsis of codebase vs breaking changes
Project does not currently define any custom dashboard widgets in
payload.config.ts, we are using the default payload dashboard.

codebase already correctly imports Lexical types via
@payloadcms/richtext-lexical/lexical (which is the recommended pattern)

CodeEditor, we are not importing or using the CodeEditor component

# Changes Made
Downgraded `next`: 15.5.9 → 15.4.11
Upgraded `lucide-react`: 0.378.0 → ^0.471.0 (latest)
Upgraded `baseline-browser-mapping` (latest)
Remove `lexical` dependency
### Further analysis after upgrade using gemini
#### 1. Payload CMS Compatibility Gap

Payload CMS 3.x relies on internal Next.js routing behaviors that were
altered in version 15.5. Staying on `15.5.9` introduced:

- **Build Failures**: Next.js 15.5's new strict TypeScript route
validation rejects Payload's auto-generated API route types
(specifically the `RouteHandlerConfig`).
    
- **Admin UI Slowness**: Documented performance regressions in 15.5
cause the Payload Admin panel to experience massive load-time spikes
(reported jumps from 2s to 30s+).

	OLD dev tested by espdesign
	` ✓ Compiled /admin/[[...segments]] in 5.5s (6831 modules)`
	NEW dev tested by espdesign
	` ✓ Compiled /admin/[[...segments]] in 9s (7912 modules
    
- **HMR Instability**: Turbopack HMR in 15.5 frequently fails to find
client modules in the manifest, leading to frequent "Module not found"
errors during development.
    
**Result**: Reverting to **15.4.11** restores the "Stable Zone" for
Payload 3.x, ensuring fast Admin UI performance and successful
production builds.

#### 2. React 19 Peer Conflict

The previous version of `lucide-react` was hard-coded to expect React 18
or older.

- **Fix**: Upgrading to the latest version of `lucide-react` adds
official support for **React 19**, resolving the peer dependency
warning.

Further changes:
```
`[baseline-browser-mapping] The data in this module is over two months old.  To ensure accurate Baseline data, please update: `npm i baseline-
browser-mapping@latest -D
```

### Migrations:
No :)
```
[22:04:26] INFO: Migration DOWN statements generation complete.
✔ No schema changes detected. Would you like to create a blank migration file? … no
```


## Test Plan
Confirm on staging.
Confirm on dev.

---------

Co-authored-by: tadjh <hello@tadjh.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants