Download Latest Version v0.51.0 source code.zip (8.7 MB) Google Add to Preferred Sources
Home / v0.50.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-09-02 37.2 kB
v0.50.0 source code.tar.gz 2026-09-02 7.0 MB
v0.50.0 source code.zip 2026-09-02 8.3 MB
Totals: 3 Items   15.4 MB 0

v0.50.0 is a monthly release with a large number of PRs to improve correctness, accessibility, and performance. It also ships HMR support, compiled keyboard shortcut dispatch, and screen reader announcements for headings and auto-links, and build-time tree-shaking annotations (in a new @lexical/compiler package). We have upgraded to pnpm 11, so if you're working directly with the monorepo you will need to upgrade as well.

Breaking Changes

  • lexical — LexicalNode.replace() no longer re-homes a named slot value. A slot value has no parent (its up-link is __slotHost), so replacing one through the tree API now fails with an actionable invariant instead of a generic parent error; use $setSlot on the owning host. $setBlocksType and the block converters skip slot values for the same reason (#8938, #8905, #8901)
  • @lexical/clipboard — The Lexical JSON clipboard payload (application/x-lexical-editor) now asks excludeFromCopy('clone') instead of 'html', matching the destination the rest of that payload already uses. Nodes that opt out of HTML export but expect to survive a clone (e.g. MarkNode) are copied again; custom excludeFromCopy implementations that keyed on 'html' for this channel should be updated (#8995)

Behavior Changes to Watch

These were merged as bug fixes rather than breaking changes, but they change observable output — check them if you snapshot HTML, assert on the DOM, or depend on the old editing behavior.

  • HTML export emits a terminating <br>. A trailing LineBreakNode in a block now exports an extra <br data-lexical-managed-linebreak="true">, mirroring what the reconciler already puts in the live DOM, so <p>a<br></p> survives an export/import round trip. Both importers drop the marker, but exported-HTML fixtures will differ (#8765)
  • Rich text mounts an aria-live region by default. HeadingAnnounceExtension (via RichTextExtension) and AutoLinkAnnounceExtension (via AutoLinkExtension) depend on AriaLiveRegionExtension, which appends a live-region <div> to document.body — or to the configured owner element. Opt out with configExtension(HeadingAnnounceExtension, {disabled: true}) (#8908, #9071)
  • Select-all delete and cut now remove the blocks. A whole-document range is widened to the top-level blocks, so the editor is left on a fresh empty paragraph instead of an emptied heading, quote or list that went on styling the next character typed — and Cmd+X now carries those blocks, so pasting restores them (#8884)
  • A formatted paragraph copies as a block. ParagraphNode.extractWithChild now keeps a fully-selected paragraph that carries alignment, indent or inline style in the payload as a block, instead of splicing its children in and dropping that formatting. Paragraphs with none of it serialize as before (#9059)
  • importJSON applies registered node replacements. JSON deserialization builds through $create, so a replacement's class is constructed and its importJSON runs; a deprecated replace without withKlass is still applied the old way (#9061, #9090)
  • Listener return types tightened. Only RootListener and EditableListener are typed to return a cleanup function; returning one from another listener is now a TypeScript error — it was never called (#8990)
  • Collab and Markdown output shifts. @lexical/yjs no longer syncs root textFormat/textStyle (#8940); Markdown import restructures nested mixed-type lists and stores fence metadata in a new mdCodeMeta node state (#8283)
  • New invariants. Replacing a slot value (#8938), an insertText anchor that is not a text node, an empty KeyboardShortcutMatch key, and a createBindingV2 getXmlText/getXmlElement that returns an un-integrated or misnamed type (#6483) now throw instead of failing later

Deprecations

  • lexical — CAN_UNDO_COMMAND and CAN_REDO_COMMAND are deprecated in favor of the canUndo / canRedo signals on HistoryExtension. A command only reports a change, so a listener registered after initialization can't read the current value; the signal always holds it (#8918)

New APIs & Features

  • @lexical/compiler — New package that injects /* @__PURE__ */ annotations and inlines the trivial side-effect-free factories (defineExtension, configExtension, safeCast, createCommand, createState, …) at build time, as a Rollup and Vite plugin. Hand-written annotations on those calls are no longer needed (#9086)
  • @lexical/extension — HMRExtension (with HMRConfig, HMROutput, HotContext) keeps an editor alive across hot module replacement. @lexical/react gains LexicalMenuOption, LexicalAutoEmbedPluginUtils, LexicalTypeaheadMenuPluginUtils and LexicalCollaborationContextUtils entry points that split values out of component modules so Fast Refresh works — the original exports are unchanged (#8959)
  • lexical / @lexical/extension — Compiled keyboard shortcut dispatch: compileKeyboardShortcuts, CONTROL_OR_ALT, CONTROL_OR_META, CONTROL_OR_OTHER_KEY, keyboardEventMaskForPlatform and the KeyboardShortcut* types in core, plus KeyboardShortcutsExtension and formatKeyboardShortcut for declaring named shortcuts and rendering them per platform (#8876)
  • @lexical/rich-text — HeadingAnnounceExtension announces heading changes to screen readers, on by default in RichTextExtension; @lexical/link's AutoLinkAnnounceExtension does the same when typing turns text into a link, on by default with AutoLinkExtension (#8908, #9071)
  • @lexical/list — Opt-in WordListImportExtension reconstructs list structure from Microsoft Word HTML (MsoListParagraph classes and mso-list metadata) on paste (#9082)
  • @lexical/rich-text — New shouldHandlePasteAsFiles config (and exported defaultShouldHandlePasteAsFiles, plus an optional third argument to registerRichText) lets an app decide that pasted files win over the incidental text/html browsers attach when an image is copied. The default is unchanged: files are handled only when the clipboard carries no text content (#8902, #8699)
  • @lexical/yjs — CreateBindingV2Options__EXPERIMENTAL allows a custom Yjs XmlText, so a Lexical document can live inside a larger shared type (#6483)
  • lexical — New $getSelectionSlotFrame (#9052) and $flushSyncAfterUpdate (#9067) exports; $isBlockFullySelected moved into core and is still re-exported from @lexical/utils (#9059); @lexical/table now exports the TableCellHeaderState type (#9038); JSDoc added across the core exports (#8895)
  • Performance — Bulk inserts and removals no longer walk the parent's children to compute an offset the selection never reads, which made those operations quadratic (#9108)

Notable Fixes

Named slots & the node tree

  • Line breaks inside a slot insert and delete correctly (#8899); a managed line break is restored in wrapped slot hosts (#9066); reading the parent style of a slot value no longer throws (#8950); a slot-bearing decorator host is deleted correctly at the selection boundary (#8905)
  • replace() keeps the parent's __size correct when handed a sibling (#8917), and splice no longer creates a sibling cycle when it re-inserts a node after the range (#8916)

Node state, copy/paste & serialization

  • HTML import/export and slot frames carry the whole node state, keeping the HTML and Lexical clipboard payloads in agreement (#9052); copy and insert keep the original node's state (#9059); list operations and DOM import/export keep the node's own state (#9050); inline node transforms keep the node and its DOM in step (#9060); code blocks keep the caret and their own attributes (#9056); blocks pasted after consecutive line breaks are preserved (#8890)
  • Nodes keep their own properties across clone, split and export: EditorState.clone() keeps _parsed (#8989), AutoLinkNode.insertNewAfter keeps its properties (#8996), a split heading keeps its format and style (#8926), split lists continue numbering from the item's value (#8913), and in the playground the Excalidraw drawing and size survive a clone (#8984), a closed collapsible no longer exports as open (#8994), mention nodes keep their display text (#8999), custom nodes keep the theme classes createDOM applied (#9049) and an unparseable data-lexical-datetime no longer breaks serialization (#9047)

Selection & editing

  • Selection and caret state are correct at block and shadow root boundaries (#9058); the block cursor shows before block decorators regardless of the preceding sibling (#8888); the select-all highlight stays visible next to boundary decorators (#8931); $extendCaretToRange's focus is a real, flippable position (#8930); Shift+Arrow extends adjacent node selections (#9067); clicking inside a selected node no longer deselects it (#8910)
  • insertNodes no longer leaves an empty paragraph after a block inserted at the end of a paragraph (#9099); insertText no longer throws when the caret is inside a segmented TextNode (#9104); Backspace works at a soft line-wrap boundary in Firefox (#9101); Enter on iOS no longer moves the caret past the acceptance boundary (#8941); iPadOS desktop-class user agents are detected (#8909); dropped files are forwarded when the drop point has no caret (#9076); clear-formatting resets the cached selection format (#8889)

Tables & lists

  • Table grid indices, cell state and boundary selection fixed (#9054); alignment covers every cell a table selection touches (#9043); inserting a column steps by the visited cell's colSpan (#8911); importDOM imports the dir attribute (#8914); toggleHeaderStyle stays inside TableCellHeaderStates (#9038); the trackTable MutationObserver is disconnected in removeListeners (#9074); text cursor placement is reliable when tapping cells on touch devices (#8827)
  • The stale depth theme class is removed when a list changes depth (#9077); rapid clicks on the same checklist checkbox are no longer throttled (#9102); focus stays in the editor when a press lands on a check list item's label (#9088)

Links, Markdown & HTML

  • TOGGLE_LINK_COMMAND's object payload no longer discards the configured attributes (#8985); $toggleLink applies the title attribute for a NodeSelection (#8993); LinkNode/AutoLinkNode getters read the latest state (#9080); middle-clicked links open in a new tab (#9078); the auto embed menu only opens when a bare link is pasted (#9091); the playground's validateUrl no longer accepts a sentence that merely contains a URL (#9097)
  • Markdown round trips keep fenced code and enclosing blocks intact (#9055); nested mixed-type lists import with the right structure (#8283); a URL containing parentheses imports correctly (#9093); no dangling closing tag when a selection slices a format to whitespace (#8961); no stray leading newline when a selection starts below the first block (#8960)
  • A trailing line break survives HTML export and re-import (#8765); exportDOM returning a DocumentFragment applies its after() replacement (#8997); parseSelector rejects an empty selector group (#9083); Prism language maps are read as own properties (#8981); a function-valued style patch is applied once to an empty element (#8912); objectKlassEquals no longer throws on undefined or prototype-less objects (#9079)

React, collaboration & history

  • Decorator portals are recreated when the editor root remounts (#8921); Placeholder uses the SSR-safe useLayoutEffect (#8906); the typeahead query updates during IME composition (#8942); plugins and hooks re-derive when their inputs change (#9051); focus is restored after dragging decorator blocks (#9064); multiple clicks are normalized (#8928)
  • Collab sync gaps between the editor state and the Yjs doc are closed, and bootstrapping the initial state no longer becomes an undo entry (#9057); only one client may bootstrap a nested editor's document, so an image caption or sticky note no longer gains a spurious leading paragraph — shouldBootstrap is documented as at-most-one-client (#9107); SharedHistoryExtension forwards the parent maxDepth (#9044) and shared history stacks record the state of the editor that actually changed, alongside fixes to overlays, hit targets and shared state at the editor boundary (#9053)

Docs & tooling

  • New Decorators concept guide (#8696), a React MathType example (#8692), a clarified vanilla quick start (#8801), documented DOMImportExtension rule evaluation order (#9089), SKIP_DOM_SELECTION_TAG behavior during the initial editor state (#8636) and $reverseDfs (#8962), plus an OpenGraph social preview for the website (#8935)
  • Upgraded to pnpm 11 (#8816), cached Playwright's apt packages in CI (#9085), extracted the internal-registry OIDC exchange into a reusable action (#9084), fixed a qs dependency vulnerability (#9072), quieted stderr noise in test-unit (#9098) and moved the playground onto ownerDocument/$getDocument() for shadow DOM safety (#8878)

What's Changed

New Contributors

Full Changelog: https://github.com/facebook/lexical/compare/v0.49.0...v0.50.0

Source: README.md, updated 2026-09-02