Releases

v53.0.3

@platejs/ai

Bug Fixes

  • Clear block streaming state when aiChat.stop() stops generation (#4945)

@platejs/link

Bug Fixes

  • Fix empty link normalization when suggestion acceptance removes the last link character (#4945)

platejs

Bug Fixes

  • Updated @platejs/utils.

@platejs/suggestion

Bug Fixes

  • Fix inline-void delete and replace suggestions around mentions and paragraph boundaries (#4945)

@platejs/utils

Bug Fixes

  • Add a trailing-block insert hook for normalization-driven insert behavior (#4945)

CHANGELOG · v53.0.2...v53.0.3 · By @felixfeng33

v53.0.0

@platejs/autoformat

Breaking Changes

  • Deprecate @platejs/autoformat. Markdown shortcuts and text substitutions are now authored as inputRules on each feature plugin, and AutoformatPlugin remains only as an inert compatibility export. (#4941)

    Migration:

    1. Remove AutoformatPlugin from your plugins and replace @platejs/autoformat after migrating rules.
    2. Replace each old AutoformatRule with the matching rule factory on the plugin that owns the feature. See the table below.
    3. Replace symbol substitutions (arrows, fractions, smart quotes, legal, math operators) with createTextSubstitutionInputRule registered on a local createSlatePlugin.
    4. Replace rules[].query with enabled on the rule factory call. Replace the global code-block guard with a per-plugin enabled check.
    5. Drop enableUndoOnDelete — undo-on-delete is the built-in behavior.
    6. Replace custom AutoformatRule definitions with createRuleFactory from platejs.
    tsx
    1// Before 2import { AutoformatPlugin } from "@platejs/autoformat"; 3 4const editor = createPlateEditor({ 5 plugins: [ 6 AutoformatPlugin.configure({ 7 options: { 8 enableUndoOnDelete: true, 9 rules: [ 10 { match: "# ", mode: "block", type: KEYS.h1 }, 11 { match: "**", mode: "mark", type: KEYS.bold }, 12 { 13 match: "* ", 14 mode: "block", 15 type: "list", 16 format: (editor) => 17 toggleList(editor, { listStyleType: KEYS.ul }), 18 }, 19 ], 20 }, 21 }), 22 ], 23}); 24 25// After 26import { BoldRules } from "@platejs/basic-nodes"; 27import { BoldPlugin } from "@platejs/basic-nodes/react"; 28import { HeadingRules } from "@platejs/basic-nodes"; 29import { H1Plugin } from "@platejs/basic-nodes/react"; 30import { BulletedListRules } from "@platejs/list"; 31import { ListPlugin } from "@platejs/list/react"; 32 33const editor = createPlateEditor({ 34 plugins: [ 35 H1Plugin.configure({ inputRules: [HeadingRules.markdown()] }), 36 BoldPlugin.configure({ 37 inputRules: [BoldRules.markdown({ variant: "*" })], 38 }), 39 ListPlugin.configure({ 40 inputRules: [BulletedListRules.markdown({ variant: "-" })], 41 }), 42 ], 43});

    Rule Map

    Basic blocks — @platejs/basic-nodes

    Old ruleNew rule
    { match: '# '..'###### ', mode: 'block', type: KEYS.h1..h6 }HxPlugin.configure({ inputRules: [HeadingRules.markdown()] }) — register on each H1Plugin..H6Plugin
    { match: '> ', mode: 'block', type: KEYS.blockquote }BlockquotePlugin.configure({ inputRules: [BlockquoteRules.markdown()] })
    { match: ['---', '—-', '___ '], mode: 'block', type: KEYS.hr }HorizontalRulePlugin.configure({ inputRules: [HorizontalRuleRules.markdown({ variant: '-' }), HorizontalRuleRules.markdown({ variant: '_' })] })

    Basic marks — @platejs/basic-nodes

    Old ruleNew ruleOwning plugin
    { match: '**', mode: 'mark', type: KEYS.bold }BoldRules.markdown({ variant: '*' })BoldPlugin
    { match: '__', mode: 'mark', type: KEYS.underline }UnderlineRules.markdown()UnderlinePlugin
    { match: '*', mode: 'mark', type: KEYS.italic }ItalicRules.markdown({ variant: '*' })ItalicPlugin
    { match: '_', mode: 'mark', type: KEYS.italic }ItalicRules.markdown({ variant: '_' })ItalicPlugin
    { match: '`', mode: 'mark', type: KEYS.code }CodeRules.markdown()CodePlugin
    { match: '~~', mode: 'mark', type: KEYS.strikethrough }StrikethroughRules.markdown()StrikethroughPlugin
    { match: '~', mode: 'mark', type: KEYS.sub }SubscriptRules.markdown()SubscriptPlugin
    { match: '^', mode: 'mark', type: KEYS.sup }SuperscriptRules.markdown()SuperscriptPlugin
    { match: '==', mode: 'mark', type: KEYS.highlight }HighlightRules.markdown({ variant: '==' })HighlightPlugin
    { match: '≡', mode: 'mark', type: KEYS.highlight }HighlightRules.markdown({ variant: '≡' })HighlightPlugin
    { match: '***', mode: 'mark', type: [bold, italic] }MarkComboRules.markdown({ variant: 'boldItalic' })BoldPlugin
    { match: '__*', mode: 'mark', type: [underline, italic] }MarkComboRules.markdown({ variant: 'italicUnderline' })BoldPlugin
    { match: '__**', mode: 'mark', type: [underline, bold] }MarkComboRules.markdown({ variant: 'boldUnderline' })BoldPlugin
    { match: '___***', mode: 'mark', type: [underline, bold, italic] }MarkComboRules.markdown({ variant: 'boldItalicUnderline' })BoldPlugin

    Register each family on its owning plugin:

    tsx
    1BoldPlugin.configure({ 2 inputRules: [ 3 BoldRules.markdown({ variant: "*" }), 4 BoldRules.markdown({ variant: "_" }), 5 MarkComboRules.markdown({ variant: "boldItalic" }), 6 MarkComboRules.markdown({ variant: "boldUnderline" }), 7 MarkComboRules.markdown({ variant: "boldItalicUnderline" }), 8 MarkComboRules.markdown({ variant: "italicUnderline" }), 9 ], 10});

    Code block — @platejs/code-block

    Old ruleNew rule
    { match: '```', mode: 'block', type: KEYS.codeBlock, format: insertEmptyCodeBlock }CodeBlockPlugin.configure({ inputRules: [CodeBlockRules.markdown({ on: 'match' })] })

    Lists — @platejs/list and @platejs/list-classic

    Old ruleNew rule
    { match: ['- ', '* '], mode: 'block', format: toggleList(..., { listStyleType: KEYS.ul }) }BulletedListRules.markdown({ variant: '-' }), BulletedListRules.markdown({ variant: '*' })
    { match: /^\d+\.$ |^\d+\)$ /, matchByRegex: true, format: toggleList(..., { listStyleType: KEYS.ol }) }OrderedListRules.markdown({ variant: '.' }), OrderedListRules.markdown({ variant: ')' })
    { match: '[] ', mode: 'block', format: toggleList(..., { listStyleType: KEYS.listTodo }) }TaskListRules.markdown({ checked: false })
    { match: '[x] ', mode: 'block', format: toggleList + setNodes({ checked: true }) }TaskListRules.markdown({ checked: true })
    tsx
    1ListPlugin.configure({ 2 inputRules: [ 3 BulletedListRules.markdown({ variant: "-" }), 4 BulletedListRules.markdown({ variant: "*" }), 5 OrderedListRules.markdown({ variant: "." }), 6 OrderedListRules.markdown({ variant: ")" }), 7 TaskListRules.markdown({ checked: false }), 8 TaskListRules.markdown({ checked: true }), 9 ], 10});

    Replace @platejs/list with @platejs/list-classic imports when using the classic list model. The factory names are identical.

    Math — @platejs/math

    Old ruleNew rule
    Inline equation $…$InlineEquationPlugin.configure({ inputRules: [MathRules.markdown({ variant: '$' })] })
    Block equation $$…$$EquationPlugin.configure({ inputRules: [MathRules.markdown({ on: 'break', variant: '$$' })] })

    Link — @platejs/link

    Old behaviorNew rule
    [text](url) markdownLinkRules.markdown()
    Autolink on pasteLinkRules.autolink({ variant: 'paste' })
    Autolink on spaceLinkRules.autolink({ variant: 'space' })
    Autolink on EnterLinkRules.autolink({ variant: 'break' })
    tsx
    1LinkPlugin.configure({ 2 inputRules: [ 3 LinkRules.markdown(), 4 LinkRules.autolink({ variant: "paste" }), 5 LinkRules.autolink({ variant: "space" }), 6 LinkRules.autolink({ variant: "break" }), 7 ], 8});

    Text substitutions (arrows, fractions, legal, math operators, smart quotes)

    Move these to a local createSlatePlugin with createTextSubstitutionInputRule:

    tsx
    1import { 2 createSlatePlugin, 3 createTextSubstitutionInputRule, 4 KEYS, 5} from "platejs"; 6 7const isTextSubstitutionBlocked = (editor) => 8 editor.api.some({ match: { type: [editor.getType(KEYS.codeBlock)] } }); 9 10const ShortcutsPlugin = createSlatePlugin({ 11 key: "shortcuts", 12 inputRules: [ 13 createTextSubstitutionInputRule({ 14 enabled: ({ editor }) => !isTextSubstitutionBlocked(editor), 15 patterns: [ 16 { format: "→", match: "->" }, 17 { format: "⇒", match: "=>" }, 18 { format: "½", match: "1/2" }, 19 { format: "™", match: ["(tm)", "(TM)"] }, 20 { format: ["“", "”"], match: '"' }, 21 ], 22 }), 23 ], 24});

    Each pattern set is just data — autoformatArrow, autoformatLegal, autoformatMath, autoformatPunctuation, autoformatSmartQuotes, and autoformatLegalHtml from the old package map 1:1 onto patterns arrays. AutoformatKit in the Plate registry is pre-built with all of them.

    Custom rules

    Old AutoformatRule objects have no direct replacement. Build a rule family with createRuleFactory:

    tsx
    1import { createRuleFactory } from "platejs"; 2 3const MyRules = { 4 markdown: createRuleFactory({ 5 type: "blockMatch", 6 match: "!! ", 7 format: "my-block", 8 }), 9}; 10 11MyPlugin.configure({ inputRules: [MyRules.markdown()] });

    Option removals

    • enableUndoOnDelete — removed. Backspace on a rule-inserted node restores the source text by default.
    • rules[].query — replaced by enabled on the rule factory call.
    • rules[].preFormat / rules[].format — replaced by rule-family format and resolve callbacks inside createRuleFactory.
    • rules[].trigger — rule families set their own trigger. Override it with the trigger option on a custom createRuleFactory call.

    See the Autoformat doc for the kit path and the Plugin Input Rules guide for the full runtime.

@platejs/basic-nodes

Breaking Changes

  • Store blockquotes as container blocks with block children. Lift every selected nested quoted block one level on Shift+Tab. Reset headings to paragraphs on Backspace at block start before any merge. (#4941)

    Migration:

    1. Update persisted values, fixtures, and tests to use block children instead of direct text children.
    2. Expect editor.tf.blockquote.toggle() to wrap or unwrap blocks instead of retagging one text block in place.
    3. Empty later quoted paragraphs delete in place on Backspace instead of jumping out of the quote.
    4. Backspace at the start of a heading now resets the heading to a paragraph before any merge.
    5. Legacy flat blockquote values still normalize on load, but persisted snapshots and fixtures should move to the new shape.
    tsx
    1// Before 2{ type: 'blockquote', children: [{ text: 'Quote' }] } 3 4// After 5{ 6 type: 'blockquote', 7 children: [{ type: 'p', children: [{ text: 'Quote' }] }], 8}

@platejs/code-block

Breaking Changes

  • Keep Backspace at the start of a non-empty first code line inside the code block. Merge an empty inner code line into the previous code line instead of unwrapping the block. (#4941)

@platejs/markdown

Breaking Changes

  • Round-trip blockquotes as nested block content instead of flat newline-packed text. Serialize image titles from node.title instead of copying the caption into the markdown title slot. Preserve MDX media attribute expressions during markdown serialization instead of stringifying them into JSON text. Serialize plain URL links back to bare URL markdown instead of bracket-link form. Round-trip footnote references and definitions as dedicated footnote nodes instead of collapsing them to plain-text fallback. (#4941)

    Migration:

    1. Update snapshots and direct value assertions to expect blockquote.children to contain block nodes such as paragraphs and lists.
    2. If you generate initial editor values from markdown, hydrate blockquotes with paragraph children instead of flat text.
    3. If you want markdown output like ![alt](url "title"), set node.title. Images without a title now serialize as ![alt](url).
    4. If you serialize MDX media nodes with expression attributes like width={640}, expect those expressions to stay as expressions instead of turning into quoted JSON.
    5. Plain URL links such as https://platejs.org now serialize as bare URLs instead of [https://platejs.org](https://platejs.org).
    6. If you enable footnote-aware markdown input, install @platejs/footnote and include BaseFootnoteReferencePlugin and BaseFootnoteDefinitionPlugin so footnote nodes have real editor semantics instead of falling back to unknown node types.
    tsx
    1// Before 2{ type: 'blockquote', children: [{ text: 'Quote\\nNext line' }] } 3 4// After 5{ 6 type: 'blockquote', 7 children: [ 8 { type: 'p', children: [{ text: 'Quote' }] }, 9 { type: 'p', children: [{ text: 'Next line' }] }, 10 ], 11}

Bug Fixes

  • Write canonical date nodes as <date value="..."/> and round-trip normalized media embed metadata (#4941)

  • Preserve unknown MDX and raw HTML block source more faithfully during markdown deserialization fallback (#4941)

@platejs/table

Breaking Changes

  • Escalate the second selectAll from the current table to the whole document. (#4941)

@platejs/core

Features

  • Add lift as a break and delete rule action for blocks that should leave one ancestor level instead of resetting or exiting. Reset the trailing block to a paragraph when splitReset handles selected heading text. (#4941)

Bug Fixes

  • Add createRuleFactory for building input rule families with overridable defaults and required options (#4941)

  • Add useNavigationHighlight(path) for React node components that need the current navigation-feedback target without reading plugin options directly (#4941)

@platejs/footnote

Features

  • Add FootnoteReferencePlugin, FootnoteDefinitionPlugin, and FootnoteInputPlugin for real footnote nodes and inline [^ combobox insertion in Plate editors. (#4941)

@platejs/date

Bug Fixes

  • Store date nodes as canonical YYYY-MM-DD values and preserve unparseable legacy text as fallback data (#4941)

@platejs/link

Bug Fixes

  • Keep pasted URLs literal inside markdown link source entry by default (#4941)

@platejs/list

Bug Fixes

  • Allow list markdown rule families to override shared runtime rule fields while keeping semantic variant and checked options (#4941)

@platejs/list-classic

Bug Fixes

  • Allow classic list markdown rule families to override shared runtime rule fields while keeping semantic variant and checked options (#4941)

@platejs/media

Bug Fixes

  • Support allowlisted Twitter/X embed snippet extraction in media embed URL transforms (#4941)

  • Normalize supported media embeds into canonical provider metadata and preserve source URLs for embed editing (#4941)

@platejs/slate

Bug Fixes

  • Updated slate, slate-dom. (081cbe9)

@platejs/toc

Bug Fixes

  • Add active section state to useTocElementState so TOC elements can mark the current heading while the document scrolls (#4941)

  • Fix TOC activation to navigate without entering block-selection mode (#4941)

@platejs/utils

Bug Fixes

  • Add KEYS.footnoteDefinition, KEYS.footnoteReference, and KEYS.footnoteInput (#4941)

CHANGELOG · v52.3.22...v53.0.0 · By @zbeyens, @github-actions[bot]

v52.3.20

@platejs/ai

Bug Fixes

  • Updated @platejs/table.

@platejs/table

Bug Fixes

  • Fix Shift+Arrow table selection to switch cells without showing a transient native range (#4931)

  • Fix merged table border toggles targeting the wrong adjacent cell (#4930)

CHANGELOG · v52.3.19...v52.3.20 · By @hhhjin, @zbeyens

v52.3.19

@platejs/ai

Bug Fixes

  • Updated @platejs/markdown.

@platejs/markdown

Bug Fixes

  • Fix ordered markdown lists starting above 1 losing their numbering after editor.tf.setValue() (#4926)

CHANGELOG · v52.3.18...v52.3.19 · By @zbeyens

v52.3.18

@platejs/ai

Bug Fixes

  • Updated @platejs/table.

@platejs/table

Bug Fixes

  • Fixed ArrowUp and ArrowDown table navigation to avoid the transient caret flash when moving between table cells. (#4923)

CHANGELOG · v52.3.17...v52.3.18 · By @hhhjin

v52.3.17

@platejs/ai

Bug Fixes

  • Updated @platejs/table.

@platejs/link

Bug Fixes

  • Fixed custom isUrl handling so it can reject internal paths like /docs and anchor links like #top instead of those shortcuts always being accepted. (#4919)

  • Fixed link validation so text starting with // is no longer treated as an internal path. This stops comment-style paste content from being autolinked by mistake, including inside code blocks. (#4917)

@platejs/table

Bug Fixes

  • Fixed table border toggling so left-border updates apply to every selected row in a multi-row cell selection instead of only the topmost row. (#4922)

CHANGELOG · v52.3.16...v52.3.17 · By @zbeyens

v52.3.16

@platejs/code-block

Bug Fixes

  • Refresh @platejs/code-block release metadata. (3465ee1)

@platejs/core

Bug Fixes

  • Republish @platejs/core to refresh the release graph for downstream packages. (#4915)

@platejs/dnd

Bug Fixes

  • Refresh @platejs/dnd release metadata. (3465ee1)

platejs

Bug Fixes

  • Updated @platejs/core, @platejs/utils.

@platejs/utils

Bug Fixes

  • Updated @platejs/core.

CHANGELOG · v52.3.15...v52.3.16 · By @zbeyens

v52.3.15

@platejs/core

Bug Fixes

  • Added normalizeStaticValue to @platejs/core for normalizing example editor values with deterministic node IDs and stable numeric createdAt metadata before SSR hydration. (#4912)

    text
    1 ```ts 2 import { normalizeStaticValue } from "@platejs/core"; 3 4 const value = normalizeStaticValue(exampleValue); 5 ```

@platejs/dnd

Bug Fixes

  • Fixed server prerender crashes in @platejs/dnd by returning inert drag-and-drop connectors when DOM DnD is unavailable, preventing Expected drag drop context during SSR builds. (#4912)

CHANGELOG · v52.3.14...v52.3.15 · By @zbeyens

v52.3.14

@platejs/code-block

Bug Fixes

  • Fixed formatCodeBlock to rewrite formatted code into real code_line nodes and trigger a redecorate pass so syntax highlighting persists after formatting. (#4907)

CHANGELOG · v52.3.13...v52.3.14 · By @zbeyens

v52.3.13

@platejs/core

Bug Fixes

  • perf(static): avoid O(n²) findPath in PlateStatic by passing pre-computed path (#4903)

    Pass pre-computed path through PlateStatic component tree instead of calling editor.api.findPath() per node. For 1,872 nodes: paragraph-only 593ms → 68.6ms (8.6x), full plugins 1,661ms → 892ms (1.9x).

CHANGELOG · v52.3.12...v52.3.13 · By @liangzr

v52.3.12

@platejs/ai

Bug Fixes

  • Fix insert-mode AI preview history so streamed chunks stay out of undo history and selection survives accept, undo, and redo (#4902)

@platejs/slate

Bug Fixes

  • Fix redo to restore selection after undoing history batches that clear the active selection (#4902)

CHANGELOG · v52.3.11...v52.3.12 · By @zbeyens

v52.3.11

platejs

Bug Fixes

  • Use compatible internal dependency ranges so platejs can resolve the current @platejs/* package graph without nested stale installs. (4af5ea4)

@platejs/utils

Bug Fixes

  • Refresh the published internal core dependency range so consumers can resolve the current Plate package graph without nested stale installs. (4af5ea4)

CHANGELOG · v52.3.10...v52.3.11 · By @zbeyens

v52.3.10

@platejs/ai

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/autoformat

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/basic-nodes

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/basic-styles

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/callout

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/caption

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/code-block

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/code-drawing

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/combobox

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/comment

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/csv

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/cursor

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/date

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/diff

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/dnd

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/docx

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/docx-io

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/emoji

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/excalidraw

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/find-replace

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/floating

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/indent

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/juice

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/layout

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/link

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/list

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/list-classic

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/markdown

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/math

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/media

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/mention

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/playwright

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/resizable

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/selection

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/slash-command

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/suggestion

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/tabbable

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/table

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/tag

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/toc

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/toggle

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

@platejs/yjs

Bug Fixes

  • Fix declaration bundling by restoring the workspace platejs build edge during package builds (#4897)

CHANGELOG · v52.3.9...v52.3.10 · By @zbeyens

v52.3.9

@platejs/code-block

Bug Fixes

  • Redecorate code blocks when the language changes to avoid stale highlighting. (#4893)

@platejs/core

Bug Fixes

  • Typed editor.api.redecorate() on the base slate extension API so shared plugins can call it without local casts. (d5dfd21)

CHANGELOG · v52.3.8...v52.3.9 · By @hhhjin, @zbeyens

v52.3.8

@platejs/ai

Bug Fixes

  • Fix replacePlaceholders replacing only the first {prompt} and markdown placeholder occurrence in AI prompt templates (#4882)

@platejs/csv

Bug Fixes

  • Fixed Papa Parse interop so native Node ESM runtimes like Vitest can import @platejs/csv without failing on a CommonJS named export. (#4890)

@platejs/docx

Bug Fixes

  • Fix RTF image extraction matching control words like shp inside longer tokens such as shppict (#4882)

@platejs/docx-io

Bug Fixes

  • Fix htmlToDocxBlob failing TypeScript 6 BlobPart checks when wrapping generated Uint8Array output. (#4891)

@platejs/layout

Bug Fixes

  • Fix invalid column group normalization preserving wrapped paragraph content instead of dropping it (#4882)

@platejs/suggestion

Bug Fixes

  • Fix suggestion metadata lookups using the actual per-suggestion keys and IDs for active descriptions, node matching, and line-break detection (#4882)

CHANGELOG · v52.3.7...v52.3.8 · By @zbeyens

v52.3.6

@platejs/docx-io

Bug Fixes

  • Fixed Mammoth comment preprocessing so block-level comment text keeps spacing instead of collapsing words together during DOCX import. (#4876)

  • Fixed decimal-bracket-end ordered lists to keep decimal DOCX numbering instead of falling back to the package default ordered style. (#4876)

  • Fixed HTML-to-DOCX list rendering so whitespace-only nodes around list items no longer drop visible list item text in generated documents. (#4876)

@platejs/selection

Bug Fixes

  • Fixed selection trigger evaluation so multiple configured triggers are checked correctly instead of stopping after the first one. (#4876)

@platejs/table

Bug Fixes

  • Reduce large-table selection latency by deriving reactive table selection from editor selectors, keeping selected-cell DOM sync at the table root, and avoiding plugin-store writes on every set_selection. (#4872)

CHANGELOG · v52.3.5...v52.3.6 · By @zbeyens, @felixfeng33

v52.3.4

@platejs/autoformat

Bug Fixes

  • Fixed readonly array support for autoformat rule options like match, trigger, type, and text format so as const rule definitions typecheck cleanly. (#4857)

@platejs/core

Bug Fixes

  • Fix PlateSlate so it passes the Slate remount key directly instead of spreading key through JSX props. (#4857)

  • Fix usePlateStore so it no longer relies on a conditional hook path that breaks React Compiler. (#4857)

  • Fix usePluginOption(plugin, 'state') so it returns the plugin option state instead of reporting an undefined option. (#4857)

  • Update internal @udecode/* dependency ranges to workspace references. (#4857)

platejs

Bug Fixes

  • Update internal @platejs/* and @udecode/* dependency ranges to workspace references. (#4857)

@platejs/slate

Bug Fixes

  • Fixed editor.tf.duplicateNodes({ block: true }) to duplicate the selected block even when nodes is omitted. (#4857)

  • Fixed withHistory(createEditor()) legacy method sync so editor, editor.api, and editor.tf all use the history-aware apply, undo, and redo methods. (#4857)

  • Fixed queryEditor, isAt, and editor.api.descendant so bottom-up location checks, point start/end checks, and non-path descendant searches behave consistently. (#4857)

  • Update internal @udecode/* dependency ranges to workspace references. (#4857)

@udecode/cn

Bug Fixes

  • Update internal @udecode/* dependency ranges to workspace references. (#4857)

@udecode/react-utils

Bug Fixes

  • Fixed createPrimitiveComponent so setProps is applied without leaking onto DOM elements. (#4857)

  • Fixed createPrimitiveComponent to preserve merged hook and consumer style props instead of overwriting hook styles when a consumer passes style.

  • Update internal @udecode/* dependency ranges to workspace references. (#4857)

@udecode/utils

Bug Fixes

  • Fixed escapeRegExp() to stop escaping plain s characters and only escape actual regular-expression syntax. (#4857)

@platejs/utils

Bug Fixes

  • Update internal @udecode/* dependency ranges to workspace references. (#4857)

CHANGELOG · v52.3.3...v52.3.4 · By @zbeyens

v52.2.0

@platejs/docx-io

Features

  • Add DOCX import/export package: (#4814)

    Import:

    • importDocx: Convert DOCX files to Plate nodes with comment extraction

    Export:

    • exportToDocx: Convert Plate content to DOCX blob
    • downloadDocx: Download DOCX files
    • exportEditorToDocx: Export and download in one call
    • DocxExportPlugin: Plugin with editor.api.docxExport and editor.tf.docxExport methods
    • DOCX_EXPORT_STYLES: Default CSS styles for Word rendering

    DOCX Static Components (in existing static files):

    • CalloutElementDocx
    • CodeBlockElementDocx, CodeLineElementDocx, CodeSyntaxLeafDocx
    • ColumnElementDocx, ColumnGroupElementDocx
    • EquationElementDocx, InlineEquationElementDocx
    • TocElementDocx

CHANGELOG · v52.1.0...v52.2.0 · By @felixfeng33

v52.1.0

@platejs/ai

Features

  • Upgraded AI SDK from v5 to v6: (#4800)

    • Updated ai peer dependency to ^6.0.0
    • Updated @ai-sdk/react peer dependency to ^3.0.0

    Enhanced AI capabilities with better table cell handling:

    • Added applyTableCellSuggestion utility for handling single-cell table operations
    • Added nestedContainerUtils for managing nested containers in table cells
    • Enhanced getMarkdown with improved table structure handling and better cell content serialization
    • Improved applyAISuggestions with more robust cell manipulation support
    • Added comprehensive tests for markdown generation from complex table structures

@platejs/markdown

Bug Fixes

  • Enhanced table cell serialization to support multiple blocks within cells: (#4800)

    • Table cells (td/th) now insert <br/> separators between multiple blocks when serializing to markdown
    • This allows markdown tables to better represent complex cell content that contains multiple paragraphs or other block elements

CHANGELOG · v52.0.17...v52.1.0 · By @felixfeng33

v52.0.16

@platejs/selection

Bug Fixes

  • Added disableSelectAll option to BlockSelectionPlugin. Set to true to disable the plugin's custom selectAll (Cmd+A) behavior and use the editor's default behavior instead. (#4799)

    text
    1 ```ts 2 BlockSelectionPlugin.configure({ 3 options: { disableSelectAll: true }, 4 }); 5 ```

CHANGELOG · v52.0.15...v52.0.16 · By @felixfeng33

v52.0.15

@platejs/combobox

Bug Fixes

  • Add userId option to editor for collaborative features (#4792)

    • Add userId option to usePlateEditor/createSlateEditor options
    • Add editor.meta.userId for accessing the current user ID
    • Breaking: Remove getUserId option from TriggerComboboxPluginOptions. Use editor.meta.userId instead.

    Migration:

    tsx
    1// Before 2MentionPlugin.configure({ 3 options: { 4 getUserId: (editor) => "123", 5 }, 6}); 7 8// After 9const editor = usePlateEditor({ 10 plugins: [MentionPlugin], 11 userId: "123", 12});

@platejs/core

Bug Fixes

  • Add userId option to editor for collaborative features (#4792)

    • Add userId option to usePlateEditor/createSlateEditor options
    • Add editor.meta.userId for accessing the current user ID
    • Breaking: Remove getUserId option from TriggerComboboxPluginOptions. Use editor.meta.userId instead.

    Migration:

    tsx
    1// Before 2MentionPlugin.configure({ 3 options: { 4 getUserId: (editor) => "123", 5 }, 6}); 7 8// After 9const editor = usePlateEditor({ 10 plugins: [MentionPlugin], 11 userId: "123", 12});

CHANGELOG · v52.0.14...v52.0.15 · By @felixfeng33

v52.0.13

@platejs/combobox

Bug Fixes

  • Add getUserId option to TriggerComboboxPluginOptions to fix combobox popover opening for all users in Yjs collaboration mode (#4762)

    When a user types a trigger character (e.g. / or @), the combobox input now stores the creator's userId. Only the creator will see the auto-focused combobox popover.

    tsx
    1SlashPlugin.configure({ 2 options: { 3 getUserId: (editor) => editor.getOption(YjsPlugin, "userId"), 4 }, 5}); 6 7MentionPlugin.configure({ 8 options: { 9 getUserId: (editor) => editor.getOption(YjsPlugin, "userId"), 10 }, 11});

@platejs/yjs

Bug Fixes

  • Add userId option to YjsPlugin for combobox collaboration support (#4762)

    tsx
    1YjsPlugin.configure({ 2 options: { 3 userId: user?.id, 4 }, 5});

CHANGELOG · v52.0.12...v52.0.13 · By @felixfeng33

v52.0.11

@platejs/ai

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/autoformat

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/basic-nodes

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/basic-styles

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/callout

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/caption

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/code-block

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/combobox

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/comment

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/core

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/csv

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/cursor

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/date

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/diff

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/dnd

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/docx

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/emoji

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/excalidraw

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/find-replace

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/floating

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/indent

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/juice

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/layout

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/link

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/list

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/list-classic

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/markdown

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/math

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/media

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/mention

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

platejs

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/playwright

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/resizable

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/selection

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/slash-command

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/suggestion

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/tabbable

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/table

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/tag

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/toc

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/toggle

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@udecode/cn

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@udecode/react-hotkeys

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@udecode/react-utils

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/utils

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

@platejs/yjs

Bug Fixes

  • Fixed "Cannot find module 'react/compiler-runtime'" error for React 18 users (#4784)

CHANGELOG · v52.0.10...v52.0.11 · By @zbeyens

v52.0.1

@platejs/ai

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/autoformat

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/basic-nodes

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/basic-styles

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/callout

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/caption

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/code-block

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/combobox

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/comment

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/core

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/csv

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/cursor

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/date

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/diff

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/dnd

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/docx

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/emoji

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/excalidraw

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/find-replace

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/floating

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/indent

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/juice

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/layout

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/link

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/list

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/list-classic

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/markdown

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/math

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/media

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/mention

Bug Fixes

  • Add React Compiler support. (#4750)

platejs

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/playwright

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/resizable

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/selection

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/slash-command

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/slate

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/suggestion

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/tabbable

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/table

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/tag

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/test-utils

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/toc

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/toggle

Bug Fixes

  • Add React Compiler support. (#4750)

@udecode/cn

Bug Fixes

  • Add React Compiler support. (#4750)

@udecode/react-hotkeys

Bug Fixes

  • Add React Compiler support. (#4750)

@udecode/react-utils

Bug Fixes

  • Add React Compiler support. (#4750)

@udecode/utils

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/utils

Bug Fixes

  • Add React Compiler support. (#4750)

@platejs/yjs

Bug Fixes

  • Add React Compiler support. (#4750)

CHANGELOG · v52.0.0...v52.0.1 · By @zbeyens

v52.0.0

@platejs/ai

Breaking Changes

@platejs/autoformat

Breaking Changes

@platejs/basic-nodes

Breaking Changes

@platejs/basic-styles

Breaking Changes

@platejs/callout

Breaking Changes

@platejs/caption

Breaking Changes

@platejs/code-block

Breaking Changes

@platejs/combobox

Breaking Changes

@platejs/comment

Breaking Changes

@platejs/core

Breaking Changes

@platejs/csv

Breaking Changes

@platejs/cursor

Breaking Changes

@platejs/date

Breaking Changes

@platejs/diff

Breaking Changes

@platejs/dnd

Breaking Changes

@platejs/docx

Breaking Changes

@platejs/emoji

Breaking Changes

@platejs/excalidraw

Breaking Changes

@platejs/find-replace

Breaking Changes

@platejs/floating

Breaking Changes

@platejs/indent

Breaking Changes

@platejs/juice

Breaking Changes

@platejs/layout

Breaking Changes

@platejs/link

Breaking Changes

@platejs/list

Breaking Changes

@platejs/list-classic

Breaking Changes

@platejs/markdown

Breaking Changes

@platejs/math

Breaking Changes

@platejs/media

Breaking Changes

@platejs/mention

Breaking Changes

platejs

Breaking Changes

@platejs/playwright

Breaking Changes

@platejs/resizable

Breaking Changes

@platejs/selection

Breaking Changes

@platejs/slash-command

Breaking Changes

@platejs/slate

Breaking Changes

@platejs/suggestion

Breaking Changes

@platejs/tabbable

Breaking Changes

@platejs/table

Breaking Changes

@platejs/tag

Breaking Changes

@platejs/test-utils

Breaking Changes

@platejs/toc

Breaking Changes

@platejs/toggle

Breaking Changes

@udecode/cn

Breaking Changes

@udecode/react-hotkeys

Breaking Changes

@udecode/react-utils

Breaking Changes

@udecode/utils

Breaking Changes

@platejs/utils

Breaking Changes

@platejs/yjs

Breaking Changes

CHANGELOG · v51.1.3...v52.0.0 · By @zbeyens

v51.1.3

@platejs/cursor

Bug Fixes

  • Avoid accessing ref during render (#4735)

@platejs/dnd

Bug Fixes

  • Avoid accessing ref during render (#4735)

@platejs/toc

Bug Fixes

  • Avoid accessing ref during render (#4735)

@udecode/react-hotkeys

Bug Fixes

  • Avoid accessing ref during render (#4735)

CHANGELOG · v51.1.2...v51.1.3 · By @zbeyens

v51.1.2

@platejs/ai

Bug Fixes

  • Format code with Biome (#4732)

@platejs/autoformat

Bug Fixes

  • Format code with Biome (#4732)

@platejs/basic-nodes

Bug Fixes

  • Format code with Biome (#4732)

@platejs/basic-styles

Bug Fixes

  • Format code with Biome (#4732)

@platejs/callout

Bug Fixes

  • Format code with Biome (#4732)

@platejs/caption

Bug Fixes

  • Format code with Biome (#4732)

@platejs/code-block

Bug Fixes

  • Format code with Biome (#4732)

@platejs/combobox

Bug Fixes

  • Format code with Biome (#4732)

@platejs/comment

Bug Fixes

  • Format code with Biome (#4732)

@platejs/core

Bug Fixes

  • Format code with Biome (#4732)

@platejs/csv

Bug Fixes

  • Format code with Biome (#4732)

@platejs/cursor

Bug Fixes

  • Format code with Biome (#4732)

@platejs/date

Bug Fixes

  • Format code with Biome (#4732)

@platejs/diff

Bug Fixes

  • Format code with Biome (#4732)

@platejs/dnd

Bug Fixes

  • Format code with Biome (#4732)

@platejs/docx

Bug Fixes

  • Format code with Biome (#4732)

@platejs/emoji

Bug Fixes

  • Format code with Biome (#4732)

@platejs/excalidraw

Bug Fixes

  • Format code with Biome (#4732)

@platejs/find-replace

Bug Fixes

  • Format code with Biome (#4732)

@platejs/floating

Bug Fixes

  • Format code with Biome (#4732)

@platejs/indent

Bug Fixes

  • Format code with Biome (#4732)

@platejs/juice

Bug Fixes

  • Format code with Biome (#4732)

@platejs/layout

Bug Fixes

  • Format code with Biome (#4732)

@platejs/link

Bug Fixes

  • Format code with Biome (#4732)

@platejs/list

Bug Fixes

  • Format code with Biome (#4732)

@platejs/list-classic

Bug Fixes

  • Format code with Biome (#4732)

@platejs/markdown

Bug Fixes

  • Format code with Biome (#4732)

@platejs/math

Bug Fixes

  • Format code with Biome (#4732)

@platejs/media

Bug Fixes

  • Format code with Biome (#4732)

@platejs/mention

Bug Fixes

  • Format code with Biome (#4732)

platejs

Bug Fixes

  • Format code with Biome (#4732)

@platejs/playwright

Bug Fixes

  • Format code with Biome (#4732)

@platejs/resizable

Bug Fixes

  • Format code with Biome (#4732)

@platejs/selection

Bug Fixes

  • Format code with Biome (#4732)

@platejs/slash-command

Bug Fixes

  • Format code with Biome (#4732)

@platejs/slate

Bug Fixes

  • Format code with Biome (#4732)

@platejs/suggestion

Bug Fixes

  • Format code with Biome (#4732)

@platejs/tabbable

Bug Fixes

  • Format code with Biome (#4732)

@platejs/table

Bug Fixes

  • Format code with Biome (#4732)

@platejs/tag

Bug Fixes

  • Format code with Biome (#4732)

@platejs/test-utils

Bug Fixes

  • Format code with Biome (#4732)

@platejs/toc

Bug Fixes

  • Format code with Biome (#4732)

@platejs/toggle

Bug Fixes

  • Format code with Biome (#4732)

@udecode/cn

Bug Fixes

  • Format code with Biome (#4732)

@udecode/react-hotkeys

Bug Fixes

  • Format code with Biome (#4732)

@udecode/react-utils

Bug Fixes

  • Format code with Biome (#4732)

@udecode/utils

Bug Fixes

  • Format code with Biome (#4732)

@platejs/utils

Bug Fixes

  • Format code with Biome (#4732)

@platejs/yjs

Bug Fixes

  • Format code with Biome (#4732)

CHANGELOG · v51.1.1...v51.1.2 · By @zbeyens

v51.0.0

@platejs/core

Breaking Changes

  • Moved static rendering functionality to @platejs/core/static / platejs/static to make @platejs/core / platejs React-free. (#4695)

    Migration To migrate, update your imports from platejs to platejs/static for all static rendering features listed below:

    • createStaticEditor, CreateStaticEditorOptions - Create static editor instance
    • serializeHtml, SerializeHtmlOptions - Serialize editor content to HTML string
    • PlateStatic, PlateStaticProps - Main static editor component
    • SlateElement, SlateElementProps - Static element component
    • SlateText, SlateTextProps - Static text component
    • SlateLeaf, SlateLeafProps - Static leaf component
    • getEditorDOMFromHtmlString

@platejs/list

Bug Fixes

  • Updated import path for SlateRenderElementProps to use the new static export from platejs/static. (#4695)

CHANGELOG · v50.3.9...v51.0.0 · By @felixfeng33

v50.3.7

@platejs/ai

Bug Fixes

  • Import createZustandStore from platejs/react (#4689)

@platejs/core

Bug Fixes

  • Decouple createSlateEditor from React: (#4689)

    • createZustandStore from @platejs/core (or platejs) is now a vanilla store without React-specific functionality (hooks).
    • The previous behavior of createZustandStore is now available in @platejs/core/react (or platejs/react). This is not part of our public API so it won't be a breaking change, but if you're using it, you'll need to import it from @platejs/core/react (or platejs/react) instead.

@platejs/media

Bug Fixes

  • Import createZustandStore from platejs/react (#4689)

CHANGELOG · v50.3.6...v50.3.7 · By @felixfeng33

v50.3.2

@platejs/floating

Bug Fixes

  • Fix: Resolve infinite loop in useFloatingToolbar hook (v2) Problem: The floating toolbar was causing infinite re-renders under certain conditions, leading to performance issues and potential browser hangs. This occurred when users interacted with text selections while the toolbar was visible. (#4646)

    WHY the change was made:

    • Infinite re-rendering was caused by the open dependency in the useEffect hook.
    • The open dependency was removed and the setOpen function was called with a functional update to access the previous state.

    HOW a consumer should update their code:

    • No action required. The change is internal and does not affect consumer code.

CHANGELOG · v50.3.1...v50.3.2 · By @narraje

v50.2.0

@platejs/ai

Features

  • Add applyAISuggestions utility for applying AI-generated content as suggestions with diff tracking (#4626)
  • Add replacePlaceholders template system supporting {prompt}, {block}, {blockSelection}, {editor} placeholders
  • Improve acceptAIChat transform to handle transient suggestions properly
  • Add block selection mode support with _replaceIds tracking
  • Fix suggestion acceptance and cleanup in chat mode

@platejs/diff

Features

  • Improve diffing of inline elements with same type (#4626)

@platejs/markdown

Features

  • Add plainMarks option to exclude specific marks from markdown serialization (#4626)
  • Improve mark handling in text serialization

@platejs/suggestion

Features

  • Add SkipSuggestionDeletes utility to extract text while excluding removed suggestions (#4626)
  • Add transient suggestions support with getTransientSuggestionKey and filtering options
  • Unify adjacent insert/remove suggestion IDs for better UI handling
  • Improve acceptSuggestion to support inline elements like links
  • Add transient parameter to getSuggestionProps and suggestion.nodes() APIs

@platejs/comment

Bug Fixes

  • Add getTransientCommentKey utility for temporary comments (#4626)

@platejs/list

Bug Fixes

  • Fix list operations with improved selection handling (#4626)

@platejs/selection

Bug Fixes

  • Improve insertBlocksAndSelect to handle fragment insertion better (#4626)

CHANGELOG · v50.1.2...v50.2.0 · By @felixfeng33

v50.0.0

@platejs/ai

Breaking Changes

  • Added AI Comment functionality to provide AI-powered text feedback and suggestions.And upgrade to AI SDK 5. (#4587)

    New Features:

    • AI Comment Integration: New utilities for AI-generated comments on selected text

      • aiCommentToRange() - Convert AI comments to text ranges with proper block mapping
      • findTextRangeInBlock() - Find text ranges within blocks for accurate comment positioning
    • Enhanced AI Chat: Improved chat functionality with comment support

      • New toolName property in chat helpers for tracking AI tools
      • Support for AI comment prompts in chat submissions
      • Added mode, toolName params to submitAIChat
      • New toolName plugin option.
    • Text Matching: Advanced text matching algorithms

      • Longest Common Subsequence (LCS) algorithm for fuzzy text matching
      • Support for multi-block text selection and comment ranges
      • Accurate text position tracking across block boundaries

    Example:

    typescript
    1// Convert AI comment to text range 2const range = aiCommentToRange(editor, { 3 blockId: 'block-1', 4 content: 'Selected text', 5 comment: 'Consider adding more detail here', 6});

    Breaking Changes:

    • streamInsertChunk has been moved from @platejs/ai to @platejs/ai/react.
    • getEditorPrompt has been moved from @platejs/ai/react to @platejs/ai.
    • getMarkdown has been moved from @platejs/ai/react to @platejs/ai.
    • promptTemplate and systemTemplate have been removed. They are now used directly in api/ai/command/route.ts.
    • The placeholder {selection} has been renamed to {blockSelection}.

@platejs/comment

Bug Fixes

  • Enhanced comment plugin to support AI-generated comments. (#4587)

    Changes:

    • Added a transient option to tf.unsetMark to allow removing all AI comments at once.

@platejs/markdown

Bug Fixes

  • Added support for preserving block IDs in markdown serialization to enable AI comment tracking. (#4587)

    Changes:

    • Enhanced Serialization: Updated serializeMd to support withBlockId option for maintaining block references

    Example:

    typescript
    1// Serialize with block IDs preserved 2const markdown = serializeMd(editor, { 3 withBlockId: true, 4}); 5// Output: <block id="block-1">Content here</block>

@platejs/selection

Bug Fixes

  • Added a selectionFallback option to api.getNodes. (#4587)
    • If selectionFallback is set to true, and no nodes are selected by blockSelection, the method will use the editor's original selection to retrieve blocks.

CHANGELOG · v49.2.22...v50.0.0 · By @felixfeng33

v49.2.8

@platejs/core

Bug Fixes

  • Added onNodeChange and onTextChange callbacks to track editor operations: (#4549)

    text
    1 - `onNodeChange`: Called for node operations (insert, remove, set, merge, split, move) 2 - `onTextChange`: Called for text operations (insert, remove) 3 4 ```tsx 5 // Usage via Plate component 6 <Plate 7 onNodeChange={({ editor, node, operation, prevNode }) => { 8 console.log('Node changed:', { node, operation, prevNode }); 9 }} 10 onTextChange={({ editor, node, operation, prevText, text }) => { 11 console.log('Text changed:', { text, prevText, operation }); 12 }} 13 />; 14 15 // Usage via plugin 16 MyPlugin.configure({ 17 handlers: { 18 onNodeChange: ({ node, operation, prevNode }) => { 19 // Handle node changes 20 }, 21 onTextChange: ({ node, operation, prevText, text }) => { 22 // Handle text changes 23 }, 24 }, 25 }); 26 ```

CHANGELOG · v49.2.7...v49.2.8 · By @zbeyens

v49.2.4

@platejs/core

Bug Fixes

  • Added useFocusedLast hook to track the last focused editor (#4537)
  • Updated EventEditorPlugin to track the last focused editor in EventEditorStore

@platejs/selection

Bug Fixes

  • Fixed duplicateBlockSelectionNodes by removing the nextBlock: true option (#4537)
  • Added mod+d hotkey to duplicate selected blocks
  • Added character input handling in block selection - typing a character now replaces selected blocks with a new block containing that character
  • Added support for node and mark operations (bold, italic, etc.)

@platejs/slate

Bug Fixes

  • Fixed duplicateNodes to allow undefined at (#4537)
  • Improved error handling by only checking for nodes parameter instead of both nodes and at

CHANGELOG · v49.2.3...v49.2.4 · By @zbeyens

v49.2.1

@platejs/ai

Bug Fixes

  • AI Streaming Improvements (#4518)

    @platejs/ai:

    • Fixed empty paragraph removal logic in streamInsertChunk to only remove true empty paragraphs (no text content)
    • Enhanced streaming support for tables and columns with proper chunk insertion
    • Fixed interface name typo: SteamInsertChunkOptionsStreamInsertChunkOptions
    • Improved markdown streaming with better handling of incomplete patterns

    @platejs/layout:

    • Added streaming support for columns in withColumn
    • Fixed column width calculations to handle edge cases

    @platejs/markdown:

    • Enhanced column deserialization with proper attribute parsing
    • Added support for column groups in markdown rules
    • Improved attribute parsing in customMdxDeserialize

@platejs/layout

Bug Fixes

  • AI Streaming Improvements (#4518)

    @platejs/ai:

    • Fixed empty paragraph removal logic in streamInsertChunk to only remove true empty paragraphs (no text content)
    • Enhanced streaming support for tables and columns with proper chunk insertion
    • Fixed interface name typo: SteamInsertChunkOptionsStreamInsertChunkOptions
    • Improved markdown streaming with better handling of incomplete patterns

    @platejs/layout:

    • Added streaming support for columns in withColumn
    • Fixed column width calculations to handle edge cases

    @platejs/markdown:

    • Enhanced column deserialization with proper attribute parsing
    • Added support for column groups in markdown rules
    • Improved attribute parsing in customMdxDeserialize

@platejs/markdown

Bug Fixes

  • AI Streaming Improvements (#4518)

    @platejs/ai:

    • Fixed empty paragraph removal logic in streamInsertChunk to only remove true empty paragraphs (no text content)
    • Enhanced streaming support for tables and columns with proper chunk insertion
    • Fixed interface name typo: SteamInsertChunkOptionsStreamInsertChunkOptions
    • Improved markdown streaming with better handling of incomplete patterns

    @platejs/layout:

    • Added streaming support for columns in withColumn
    • Fixed column width calculations to handle edge cases

    @platejs/markdown:

    • Enhanced column deserialization with proper attribute parsing
    • Added support for column groups in markdown rules
    • Improved attribute parsing in customMdxDeserialize

CHANGELOG · v49.2.0...v49.2.1 · By @felixfeng33

v49.2.0

@platejs/list

Features

  • Added expandListItemsWithChildren to automatically include list item children when selecting blocks for operations like drag-and-drop. (#4514)
  • Added getListChildren to get all child list items (with bigger indent) of a given list item.

CHANGELOG · v49.1.13...v49.2.0 · By @zbeyens

v49.1.13

@platejs/list

Bug Fixes

  • Fixed toggleList to respect list plugin's inject match when applying list transforms. (#4512)

@platejs/slate

Bug Fixes

  • Added combineTransformMatchOptions utility for combining match predicates in transforms. This utility provides default matching behavior that matches the native Slate transform behavior when no match is provided. (#4512)
  • Added editor.meta.isNormalizing flag to track when the editor is normalizing nodes. This flag is automatically set to true during editor.tf.normalizeNode and plugin.normalizeInitialValue and restored to its previous value when normalization completes.

@platejs/table

Bug Fixes

  • Fixed table cell selection "remove marks" and "set nodes" transforms (e.g. align, list) (#4512)

CHANGELOG · v49.1.12...v49.1.13 · By @zbeyens

v49.1.9

@platejs/markdown

Bug Fixes

  • Fixed markdown serialization of indented lists when using custom paragraph node types. The serializer now correctly identifies custom paragraph nodes instead of only looking for the default 'p' type. (#4493)

CHANGELOG · v49.1.8...v49.1.9 · By @felixfeng33

v49.1.8

@platejs/markdown

Bug Fixes

  • Fix custom plugin key handling in markdown serialization/deserialization. Ensures plugin keys are properly resolved throughout the conversion process for custom plugin configurations. (#4486)

CHANGELOG · v49.1.7...v49.1.8 · By @felixfeng33

v49.1.7

@platejs/dnd

Bug Fixes

  • Added support for dragging multiple blocks using editor's native selection (#4481)

    • Multiple blocks can now be dragged using the editor's native selection, not just with block-selection
    • Simplified useDndNode hook implementation by removing complex preview logic

CHANGELOG · v49.1.6...v49.1.7 · By @felixfeng33

v49.1.6

@platejs/markdown

Bug Fixes

  • Add support for display text markdown format for mentions (#4468)

    • Updated remarkMention plugin to only support the [display text](mention:id) format
    • Dropped support for legacy @username format
    • Mentions now require an explicit display text and ID structure
    • Enables full names, spaces, and special characters in mention display text

CHANGELOG · v49.1.5...v49.1.6 · By @felixfeng33

v49.1.4

@platejs/core

Bug Fixes

  • Fixed getSelectedDomFragment to correctly handle partial text selections at the beginning or end of selected blocks by deserializing only the selected portion instead of the entire block. (#4463)

CHANGELOG · v49.1.3...v49.1.4 · By @felixfeng33

v49.1.3

@platejs/core

Bug Fixes

  • Added editor.tf.nodeId.normalize() API to manually normalize node IDs in the document. (#4454)

    text
    1 ```ts 2 // Normalize all nodes in the document to ensure they have IDs 3 editor.tf.nodeId.normalize(); 4 ```
    • Added normalizeNodeId pure function to normalize node IDs in a value without using editor operations.

      ts
      1import { normalizeNodeId } from '@platejs/core'; 2 3// Normalize a value without editor operations 4const normalizedValue = normalizeNodeId(value, { 5 idKey: 'id', 6 idCreator: () => nanoid(10), 7 filterInline: true, 8 filterText: true, 9});

      This is useful when the value is passed from server to client-side editor.

    • Added getFragment() API method to ViewPlugin for accessing the selected DOM fragment.

    usePlateViewEditor:

    • Added onReady handler support for async rendering with automatic re-render when isAsync is true
    typescript
    1// New API usage 2const fragment = editor.getApi(ViewPlugin).getFragment(); 3 4// Async rendering support 5const editor = usePlateViewEditor({ 6 onReady: (ctx) => { 7 // Called when editor is ready, supports async rendering 8 }, 9});

CHANGELOG · v49.1.2...v49.1.3 · By @felixfeng33

v49.1.1

@platejs/link

Bug Fixes

  • Fix markdown headings being incorrectly converted to links (#4452)

    The LinkPlugin's validateUrl function now properly distinguishes between markdown headings and anchor links. Previously, any string starting with # was treated as a valid link, causing markdown headings like # heading1 to be converted to links when pasted. Now, the function checks for the markdown heading pattern (hash symbols followed by a space) and correctly rejects these as invalid URLs while still allowing valid anchor links like #section-name.

CHANGELOG · v49.1.0...v49.1.1 · By @zbeyens

v49.1.0

@platejs/list-classic

Features

  • Added task list functionality to @platejs/list-classic. (36211fa)

    • Added BaseTaskListPlugin with support for task lists (checklists)
    • Added checked property to TTodoListItemElement type for tracking task completion state
    • Added useTodoListElement and useTodoListElementState hooks for task list item management
    • Added getPropsIfTaskList utility to check if an element is a task list
    • Added normalization logic to ensure consistent checked property state
    • Added toggleTaskList transform to convert between regular lists and task lists
    tsx
    1// Before - only regular lists 2createListPlugin(); 3 4// After - with task list support 5createListPlugin(); 6 7// Toggle task list 8editor.tf.toggle.list({ listType: 'taskList' });

CHANGELOG · v49.0.19...v49.1.0 · By @zbeyens

v49.0.17

@platejs/markdown

Bug Fixes

  • Added spread option to control list spacing in markdown serialization. (#4440)

    Added a new optional spread property to SerializeMdOptions:

    • When spread is false (default), lists are rendered compactly
    • When spread is true, lists have double line breaks between items

    Before (default):

    markdown
    11. Item 1 22. Item 2

    After (with spread: true):

    markdown
    11. Item 1 2 32. Item 2

CHANGELOG · v49.0.16...v49.0.17 · By @zbeyens

v49.0.16

@platejs/core

Bug Fixes

  • Expose mimeType to plugin parser functions (#4441)

  • Added comprehensive copy functionality and view editor support for static rendering. (#4431)

    New Components:

    • Added PlateView component for static editor rendering with copy support
    • Added usePlateViewEditor hook for creating memoized static editors

    Static Editor Enhancements:

    • Added withStatic HOC to enhance editors with static rendering capabilities
    • Added ViewPlugin that enables copy operations in static editors
    • Added getStaticPlugins to configure plugins for static rendering
    • Added onCopy handler that properly serializes content with x-slate-fragment format

    New Utilities:

    • Added getSelectedDomBlocks to extract selected DOM elements with Slate metadata
    • Added getSelectedDomNode to get DOM nodes from browser selection
    • Added isSelectOutside to check if selection is outside editor bounds
    • Added getPlainText to recursively extract plain text from DOM nodes

    This enables seamless copy operations from static Plate editors, allowing content to be pasted into other Slate editors while preserving rich formatting and structure.

CHANGELOG · v49.0.15...v49.0.16 · By @delijah, @felixfeng33

v49.0.15

@platejs/core

Bug Fixes

  • Updated SlateElementProps, SlateTextProps, SlateLeafProps, PlateElementProps, PlateTextProps, and PlateLeafProps to properly type the attributes property to unknown object. (#4428)

@platejs/link

Bug Fixes

  • Improved return type of getLinkAttributes to be more specific and type-safe. (#4428)

    ts
    1// The function now returns a properly typed object 2const attributes = getLinkAttributes(editor, linkElement); 3// attributes is now properly typed as Pick<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'target'> & UnknownObject

@platejs/selection

Bug Fixes

  • fix(selection): skip empty blocks in copySelectedBlocks to prevent duplication (#4415)

@udecode/react-utils

Bug Fixes

  • Critical fix for 49.0.13 (#4434)

CHANGELOG · v49.0.14...v49.0.15 · By @zbeyens

v49.0.12

@platejs/ai

Bug Fixes

  • Fixed AI streaming compatibility with markdown serialization changes. Streaming functions now explicitly set preserveEmptyParagraphs: false to prevent zero-width space interference during real-time streaming operations. (#4416)

@platejs/markdown

Bug Fixes

  • Fixed an issue where empty paragraphs were lost during markdown serialization and deserialization. Empty paragraphs are now preserved using zero-width spaces (\u200B) internally. (#4416)

    text
    1 ```ts 2 // Before: Empty paragraphs would disappear 3 const markdown = serializeMd(editor); // "Text\n\nMore text" → "Text\nMore text" 4 5 // After: Empty paragraphs are preserved 6 const markdown = serializeMd(editor); // "Text\n\nMore text" → "Text\n\nMore text" 7 ```
    • Added preserveEmptyParagraphs option to control this behavior (defaults to true)

CHANGELOG · v49.0.11...v49.0.12 · By @zbeyens

v49.0.11

@platejs/core

Bug Fixes

  • Fixed BR tags between block elements from Google Docs creating two empty paragraphs instead of one. The deserialization now correctly converts BR tags between blocks to single empty paragraphs. (#4411)

CHANGELOG · v49.0.10...v49.0.11 · By @zbeyens

v49.0.7

@platejs/dnd

Bug Fixes

  • Fixed an issue where drag and drop functionality would not work properly with multiple selected blocks. (#4385)
  • Added logic to ensure only one drop position exists between any two nodes to prevent visual blinking during drag operations.

@platejs/selection

Bug Fixes

  • Added sort and collapseTableRows options to editor.blockSelection.getNodes() method. (#4385)
  • Added editor.blockSelection.first to get the first selected node.
  • Added normalize function to handle table selection logic in useSelectionArea hook for improved table row and table element selection behavior.
    • It is now possible to select the entire table (table), but the rows (tr) will only be selected if your selection box is within the table.

CHANGELOG · v49.0.6...v49.0.7 · By @felixfeng33

v49.0.4

@platejs/core

Bug Fixes

  • Fixes #4374 (#4373)

  • Prevent rendering the editor until the value is loaded (when value is async or skipInitialization is true).

  • Added support for both synchronous and asynchronous functions in the value option for createPlateEditor and usePlateEditor. If async, usePlateEditor will trigger a re-render when the value is loaded.

  • Added onReady callback option to createPlateEditor and usePlateEditor called after (async) editor initialization.

    ts
    1const editor = usePlateEditor({ 2 value: async () => { 3 const response = await fetch('/api/document'); 4 const data = await response.json(); 5 return data.content; 6 }, 7 onReady: ({ editor, value }) => { 8 console.info('Editor ready with value:', value); 9 }, 10});

CHANGELOG · v49.0.3...v49.0.4 · By @zbeyens

v49.0.0

@udecode/plate-ai

Breaking Changes

  • Copilot API method changes: (#4327)

    • editor.api.copilot.accept is now editor.tf.copilot.accept.
    • editor.api.copilot.acceptNextWord is now editor.tf.copilot.acceptNextWord.
    • editor.api.copilot.reset is now editor.api.copilot.reject.
  • Removed Default Shortcuts for Copilot:

    • Only accept (Tab) and reject (Escape) shortcuts are included by default for CopilotPlugin.
    • acceptNextWord and triggerSuggestion shortcuts must now be configured manually using the shortcuts field when configuring the plugin.
    • Example:
      tsx
      1CopilotPlugin.configure({ 2 // ... other options 3 shortcuts: { 4 acceptNextWord: { 5 keys: 'mod+right', 6 }, 7 triggerSuggestion: { 8 keys: 'ctrl+space', 9 }, 10 }, 11});
  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-alignment

Breaking Changes

  • Package @udecode/plate-alignment has been deprecated. (#4327)

    • TextAlignPlugin (formerly AlignPlugin) has been moved to the @platejs/basic-styles package.

    • Migration:

      • Remove @udecode/plate-alignment from your dependencies.
      • Add @platejs/basic-styles to your dependencies if not already present.
      • Import TextAlignPlugin from @platejs/basic-styles/react.
    • Renamed AlignPlugin to TextAlignPlugin and changed plugin key from 'align' to 'textAlign'.

      ts
      1// Before 2import { AlignPlugin } from '@udecode/plate-alignment/react'; 3 4// After 5import { TextAlignPlugin } from '@platejs/basic-styles/react';
    • setAlign signature change:

    ts
    1// Before 2setAlign(editor, { value: 'center', setNodesOptions }); 3 4// After 5setAlign(editor, 'center', setNodesOptions);
    • Removed useAlignDropdownMenu and useAlignDropdownMenuState. Use it in your own codebase, for example:
    tsx
    1export function AlignToolbarButton() { 2 const editor = useEditorRef(); 3 const value = useSelectionFragmentProp({ 4 defaultValue: 'start', 5 structuralTypes, 6 getProp: (node) => node.align, 7 }); 8 9 const onValueChange = (newValue: string) => { 10 editor.tf.textAlign.setNodes(newValue as Alignment); 11 editor.tf.focus(); 12 }; 13 14 // ... 15}

Features

  • New transform method to AlignPlugin: (#4327)
    • editor.tf.textAlign.setNodes - Transform method for setting alignment values. Alias to setAlign

@udecode/plate-autoformat

Breaking Changes

  • Replaced BaseAutoformatPlugin with AutoformatPlugin, which is no longer a React plugin. Migration: Replace @udecode/plate-autoformat/react import with @udecode/plate-autoformat. (#4327)

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-basic-elements

Breaking Changes

  • Package @udecode/plate-basic-elements has been deprecated. (#4327)
  • BasicElementsPlugin has been renamed to BasicBlocksPlugin.
  • Its plugins have been moved to the new @platejs/basic-nodes package.
  • Migration:
    • Replace @udecode/plate-basic-elements with @platejs/basic-nodes in your dependencies.
    • Update import paths from @udecode/plate-basic-elements/react to @platejs/basic-nodes/react.
    • For detailed changes to individual plugins, default HTML tags, and shortcut configurations, refer to the changeset for @platejs/basic-nodes.

@udecode/plate-basic-marks

Breaking Changes

  • Package @udecode/plate-basic-marks has been deprecated. (#4327)
  • Its plugins have been moved to the new @platejs/basic-nodes package.
  • Migration:
    • Replace @udecode/plate-basic-marks with @platejs/basic-nodes in your dependencies.
    • Update import paths from @udecode/plate-basic-marks/react to @platejs/basic-nodes/react.
    • For detailed changes to individual plugins, default HTML tags, and shortcut configurations, refer to the changeset for @platejs/basic-nodes.

@udecode/plate-basic-nodes

Breaking Changes

  • The packages @udecode/plate-basic-elements and @udecode/plate-basic-marks have been deprecated. All their plugins are now consolidated into the new @platejs/basic-nodes package. (#4327)
  • Migration:
    • Replace @udecode/plate-basic-elements and @udecode/plate-basic-marks in your dependencies with @platejs/basic-nodes.
    • Update all import paths from @udecode/plate-basic-elements/react or @udecode/plate-basic-marks/react to @platejs/basic-nodes/react.
    • CodeBlockPlugin is not part of @platejs/basic-nodes. Ensure it is imported from @platejs/code-block/react.
  • SkipMarkPlugin (standalone) is removed. Its functionality is now built into the core editor. To enable boundary clearing for a specific mark, configure the mark plugin directly: plugin.configure({ rules: { selection: { affinity: 'outward' } } }).
  • Default HTML Tag Changes:
    • Blocks: Element plugins in @udecode/plate-basic-nodes (e.g., BlockquotePlugin, HeadingPlugin, HorizontalRulePlugin) now default to rendering with specific HTML tags (<blockquote>, <h1>-<h6>, <hr> respectively). ParagraphPlugin still defaults to <div>. If you relied on previous defaults or need different tags, provide a custom component or use the render.as option.
    • Marks: Mark plugins in @udecode/plate-basic-nodes (e.g., BoldPlugin, CodePlugin, ItalicPlugin) now default to specific HTML tags (<strong>, <code>, <em> respectively). If you relied on previous defaults or need different tags, provide a custom component or use the render.as option.
  • Removed Default Shortcuts:
    • Default keyboard shortcuts are no longer bundled with most plugins (exceptions: bold, italic, underline).
    • Configure shortcuts manually via the shortcuts field in plugin configuration.
    • Example (Block Plugins):
      ts
      1H1Plugin.configure({ shortcuts: { toggle: { keys: 'mod+alt+1' } } }); 2BlockquotePlugin.configure({ 3 shortcuts: { toggle: { keys: 'mod+shift+period' } }, 4});
    • Example (Mark Plugins):
      ts
      1CodePlugin.configure({ shortcuts: { toggle: { keys: 'mod+e' } } }); 2StrikethroughPlugin.configure({ 3 shortcuts: { toggle: { keys: 'mod+shift+x' } }, 4}); 5SubscriptPlugin.configure({ 6 shortcuts: { toggle: { keys: 'mod+comma' } }, 7}); 8SuperscriptPlugin.configure({ 9 shortcuts: { toggle: { keys: 'mod+period' } }, 10}); 11HighlightPlugin.configure({ 12 shortcuts: { toggle: { keys: 'mod+shift+h' } }, 13});

Features

  • New toggle Transforms Added: (#4327)
    • Block plugins with new toggle transforms: BlockquotePlugin, H1Plugin, H2Plugin, H3Plugin, H4Plugin, H5Plugin, H6Plugin.
    • All mark plugins in this package now also feature a toggle transform, including: BoldPlugin, ItalicPlugin, UnderlinePlugin, CodePlugin, StrikethroughPlugin, SubscriptPlugin, SuperscriptPlugin, KbdPlugin, HighlightPlugin.
  • Individual Heading Plugins Available:
    • H1Plugin, H2Plugin, H3Plugin, H4Plugin, H5Plugin, and H6Plugin offer a flexible alternative to the general HeadingPlugin, allowing granular control over heading level inclusion and configuration (e.g., custom components, shortcuts per level).
  • Plugin Consolidations into @udecode/plate-basic-nodes:
    • KbdPlugin (formerly from @udecode/plate-kbd).
    • HighlightPlugin (formerly from @udecode/plate-highlight).

@udecode/plate-block-quote

Breaking Changes

  • Package @udecode/plate-block-quote has been deprecated. (#4327)
  • BlockquotePlugin has been moved to the @platejs/basic-nodes package.
  • Migration:
    • Remove @udecode/plate-block-quote from your dependencies.
    • Add @platejs/basic-nodes to your dependencies if not already present.
    • Import BlockquotePlugin from @platejs/basic-nodes/react.

@udecode/plate-break

Breaking Changes

  • Package @udecode/plate-break has been deprecated. (#4327)

  • SoftBreakPlugin has been removed. Migration:

    • For shift+enter rules: no migration is needed - this behavior is built into Slate by default.
    • For enter rules: use plugin.configure({ rules: { break: { default: 'lineBreak' } } }) to insert a line break instead of a hard break on Enter keydown when the selection is within the configured node type.
    • For more complex break rules: use overrideEditor to override the insertBreak transform with custom logic.
  • ExitBreakPlugin has been moved to @platejs/utils (which is re-exported via platejs) with a simplified API and improved behavior.

    text
    1 - **Behavior Change**: Instead of always exiting to the root level of the document, exiting will now insert a block to the nearest exitable ancestor that has `isStrictSiblings: false`. This means deeply nested structures (like tables in columns) are exitable at many levels. 2 - Migration: 3 4 - Remove `@udecode/plate-break` from your dependencies. 5 - Replace `@udecode/plate-break` import with `platejs`. 6 - **Important**: If not using Plate plugins, you must set `isStrictSiblings: true` on your custom node plugins that can't have paragraph siblings for exit break to work correctly. 7 - Replace complex rule-based configuration with simple shortcuts: 8 9 ```tsx 10 // Before (old API) 11 ExitBreakPlugin.configure({ 12 options: { 13 rules: [ 14 { hotkey: 'mod+enter' }, 15 { hotkey: 'mod+shift+enter', before: true }, 16 ], 17 }, 18 }); 19 20 // After (new API) 21 ExitBreakPlugin.configure({ 22 shortcuts: { 23 insert: { keys: 'mod+enter' }, 24 insertBefore: { keys: 'mod+shift+enter' }, 25 }, 26 }); 27 ```

@udecode/plate-callout

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-caption

Breaking Changes

  • CaptionPlugin option options.plugins (accepting an array of PlatePlugin) has been renamed to options.query.allow (accepting an array of plugin keys). (#4327)

  • Migration:

    text
    1 ```tsx 2 // Before 3 CaptionPlugin.configure({ 4 options: { 5 plugins: [ImagePlugin], // ImagePlugin is an example 6 }, 7 }); 8 9 // After 10 CaptionPlugin.configure({ 11 options: { 12 query: { 13 allow: [ImagePlugin.key], // Use the plugin's key 14 }, 15 }, 16 }); 17 ```
  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-code-block

Breaking Changes

  • CodeBlockPlugin now defaults to rendering the code block container with a <pre> HTML tag if no custom component is provided for CodeBlockElement (or the plugin key code_block). (#4327)

@udecode/plate-combobox

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-comments

Breaking Changes

  • CommentsPlugin has been renamed to CommentPlugin. (#4327)

  • Update imports and plugin configurations accordingly.

    • Example: CommentsPlugin.key becomes CommentPlugin.key.
  • Package name has been changed to @platejs/comment.

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-core

Breaking Changes

  • editor.getType() now takes a pluginKey: string instead of a plugin: PlatePlugin instance. (#4327)

    • Example: Use editor.getType(ParagraphPlugin.key) instead of editor.getType(ParagraphPlugin).
  • Plugins without a key property will not be registered into the editor.

  • Passing disabled: true prop to PlateContent will now also set the editor to readOnly: true state internally.

  • Editor DOM state properties have been moved under editor.dom namespace:

    • editor.currentKeyboardEvent is now editor.dom.currentKeyboardEvent.
    • editor.prevSelection is now editor.dom.prevSelection.
  • Editor metadata properties have been moved under editor.meta namespace:

    • editor.isFallback is now editor.meta.isFallback
    • editor.key is now editor.meta.key
    • editor.pluginList is now editor.meta.pluginList
    • editor.shortcuts is now editor.meta.shortcuts
    • editor.uid is now editor.meta.uid
  • NodeIdPlugin is now enabled by default as part of the core plugins. This automatically assigns unique IDs to block nodes.

    • Migration: If you were not previously using NodeIdPlugin and wish to maintain the old behavior (no automatic IDs), explicitly disable it in your editor configuration:
      ts
      1const editor = usePlateEditor({ 2 // ...other options 3 nodeId: false, // Disables automatic node ID generation 4});
  • The components prop has been removed from serializeHtml and PlateStatic.

    • Migration: Pass the components to createSlateEditor({ components }) or the individual plugins instead.
  • Plugin Shortcuts System Changes:

    • Shortcut keys defined in editor.shortcuts are now namespaced by the plugin key (e.g., code.toggle for CodePlugin).
    • The priority property for shortcuts is used to resolve conflicts when multiple shortcuts share the exact same key combination, not for overriding shortcuts by name.
    • preventDefault for plugin shortcuts now defaults to true, unless the handler returns false (i.e. not handled). This means browser default actions for these key combinations will be prevented unless explicitly allowed.
      • Migration: If you need to allow browser default behavior for a specific shortcut, set preventDefault: false in its configuration:
        ts
        1MyPlugin.configure({ 2 shortcuts: { 3 myAction: { 4 keys: 'mod+s', 5 preventDefault: false, // Example: Allow browser's default save dialog 6 }, 7 }, 8});
  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

Features

  • New editor DOM state fields available under editor.dom: (#4327)
    • editor.dom.composing: Boolean, true if the editor is currently composing text (e.g., during IME input).
    • editor.dom.focused: Boolean, true if the editor currently has focus.
    • editor.dom.readOnly: Boolean, true if the editor is in read-only mode. Passing the readOnly prop to PlateContent will sync its value to this state and to the useEditorReadOnly hook.
  • New editor metadata fields:
    • editor.meta.components - stores the plugin components by key
  • New hook useEditorComposing: Allows subscription to the editor's composing state (editor.dom.composing) outside of PlateContent.
  • createPlateEditor and usePlateEditor now accept a readOnly option to initialize the editor in a read-only state. For dynamic read-only changes after initialization, continue to use the readOnly prop on the <Plate> or <PlateContent> component.
  • New plugin field: editOnly (boolean or object).
    • When true or when specific properties are true in the object, Plate will disable certain plugin behaviors (handlers, rendering, injections) in read-only mode and re-enable them if the editor becomes editable.
    • By default, render, handlers, and inject are considered edit-only (true). normalizeInitialValue defaults to always active (false).
    • Example: editOnly: { render: false, normalizeInitialValue: true } would make rendering active always, but normalization only in edit mode.
  • New plugin field: render.as (keyof HTMLElementTagNameMap).
    • Specifies the default HTML tag name to be used by PlateElement (default: 'div') or PlateLeaf (default: 'span') when rendering the node, but only if no custom node.component is provided for the plugin.
    • Example: render: { as: 'h1' } would make the plugin render its node as an <h1> tag by default without the need to provide a custom component.
  • New plugin field: node.isContainer (boolean).
    • When true, indicates that the plugin's elements are primarily containers for other content.
  • New plugin field: node.isStrictSiblings (boolean).
    • When true, indicates that the element enforces strict sibling type constraints and only allows specific siblings (e.g., td can only have td siblings, column can only have column siblings).
    • Used by editor.tf.insertExitBreak functionality to determine appropriate exit points in nested structures.
  • New plugin field: rules (object).
    • Configures common editing behaviors declaratively instead of overriding editor methods. See documentation for more details.
    • rules.break: Controls Enter key behavior (empty, default, emptyLineEnd, splitReset)
    • rules.delete: Controls Backspace key behavior (start, empty)
    • rules.merge: Controls block merging behavior (removeEmpty)
    • rules.normalize: Controls normalization behavior (removeEmpty)
    • rules.selection: Controls cursor positioning behavior (affinity)
    • rules.match: Conditional rule application based on node properties
  • Plugin shortcuts can now automatically leverage existing plugin transforms by specifying the transform name, in addition to custom handlers.
  • New editor transform methods for keyboard handling:
    • editor.tf.escape: Handle Escape key events. Returns true if the event is handled.
    • editor.tf.moveLine: Handle ArrowDown and ArrowUp key events with reverse option for direction. Returns true if the event is handled.
    • editor.tf.selectAll: Handle Ctrl/Cmd+A key events for selecting all content. Returns true if the event is handled.
    • editor.tf.tab: Handle Tab and Shift+Tab key events with reverse option for Shift+Tab. Returns true if the event is handled.

Bug Fixes

  • Fixed an issue where editor.api and editor.tf (transforms) were not consistently available in the props passed to default element components when no custom component was provided for a plugin. (#4327)

@udecode/plate-csv

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-cursor

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-date

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-diff

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-dnd

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-docx

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-emoji

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-excalidraw

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-find-replace

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-floating

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-font

Breaking Changes

  • Removed setBlockBackgroundColor (#4327)

  • Removed setFontSize – use tf.fontSize.addMark instead:

    ts
    1// Before 2editor.api.fontSize.addMark('16px'); 3 4// After 5editor.tf.fontSize.addMark('16px');
    • Removed useColorInput. Use it in your own codebase, for example:
    tsx
    1function ColorInput() { 2 const inputRef = React.useRef<HTMLInputElement | null>(null); 3 4 const onClick = () => { 5 inputRef.current?.click(); 6 }; 7 8 // ... 9}
    • Removed useColorsCustom and useColorsCustomState. Use it in your own codebase, for example:
    tsx
    1function ColorCustom({ color, colors, customColors, updateCustomColor }) { 2 const [customColor, setCustomColor] = React.useState<string>(); 3 const [value, setValue] = React.useState<string>(color || '#000000'); 4 5 React.useEffect(() => { 6 if ( 7 !color || 8 customColors.some((c) => c.value === color) || 9 colors.some((c) => c.value === color) 10 ) { 11 return; 12 } 13 14 setCustomColor(color); 15 }, [color, colors, customColors]); 16 17 const computedColors = React.useMemo( 18 () => 19 customColor 20 ? [ 21 ...customColors, 22 { 23 isBrightColor: false, 24 name: '', 25 value: customColor, 26 }, 27 ] 28 : customColors, 29 [customColor, customColors] 30 ); 31 32 const updateCustomColorDebounced = React.useCallback( 33 debounce(updateCustomColor, 100), 34 [updateCustomColor] 35 ); 36 37 const inputProps = { 38 value, 39 onChange: (e: React.ChangeEvent<HTMLInputElement>) => { 40 setValue(e.target.value); 41 updateCustomColorDebounced(e.target.value); 42 }, 43 }; 44 45 // ... 46}
    • Removed useColorDropdownMenu and useColorDropdownMenuState. Use it in your own codebase, for example:
    tsx
    1export function FontColorToolbarButton({ nodeType }) { 2 const editor = useEditorRef(); 3 4 const selectionDefined = useEditorSelector( 5 (editor) => !!editor.selection, 6 [] 7 ); 8 9 const color = useEditorSelector( 10 (editor) => editor.api.mark(nodeType) as string, 11 [nodeType] 12 ); 13 14 const [selectedColor, setSelectedColor] = React.useState<string>(); 15 const [open, setOpen] = React.useState(false); 16 17 const onToggle = React.useCallback( 18 (value = !open) => { 19 setOpen(value); 20 }, 21 [open, setOpen] 22 ); 23 24 const updateColor = React.useCallback( 25 (value: string) => { 26 if (editor.selection) { 27 setSelectedColor(value); 28 editor.tf.select(editor.selection); 29 editor.tf.focus(); 30 editor.tf.addMarks({ [nodeType]: value }); 31 } 32 }, 33 [editor, nodeType] 34 ); 35 36 const clearColor = React.useCallback(() => { 37 if (editor.selection) { 38 editor.tf.select(editor.selection); 39 editor.tf.focus(); 40 if (selectedColor) { 41 editor.tf.removeMarks(nodeType); 42 } 43 onToggle(); 44 } 45 }, [editor, selectedColor, onToggle, nodeType]); 46 47 React.useEffect(() => { 48 if (selectionDefined) { 49 setSelectedColor(color); 50 } 51 }, [color, selectionDefined]); 52 53 // ... 54}

@udecode/plate-heading

Breaking Changes

  • Package @udecode/plate-heading has been deprecated. (#4327)
    • HeadingPlugin and individual heading plugins (e.g., H1Plugin) have been moved to @platejs/basic-nodes.
      • Migration: Import from @platejs/basic-nodes/react (e.g., import { HeadingPlugin } from '@platejs/basic-nodes/react';).
    • TocPlugin has been moved to @platejs/toc.
      • Migration: Add @platejs/toc to your dependencies and import TocPlugin from @platejs/toc/react.
  • Remove @udecode/plate-heading from your dependencies.

@udecode/plate-highlight

Breaking Changes

  • Package @udecode/plate-highlight has been deprecated. (#4327)
  • HighlightPlugin has been moved to the @platejs/basic-nodes package.
  • Migration:
    • Remove @udecode/plate-highlight from your dependencies.
    • Add @platejs/basic-nodes to your dependencies if not already present.
    • Import HighlightPlugin from @platejs/basic-nodes/react.

@udecode/plate-horizontal-rule

Breaking Changes

  • Package @udecode/plate-horizontal-rule has been deprecated. (#4327)
  • HorizontalRulePlugin has been moved to the @platejs/basic-nodes package.
  • Migration:
    • Remove @udecode/plate-horizontal-rule from your dependencies.
    • Add @platejs/basic-nodes to your dependencies if not already present.
    • Import HorizontalRulePlugin from @platejs/basic-nodes/react.

@udecode/plate-indent

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-indent-list

Breaking Changes

  • Package @udecode/plate-indent-list has been renamed to @platejs/list. (#4327)
  • Migration:
    • Rename all import paths from @udecode/plate-indent-list to @platejs/list.
    • Update your package.json: remove @udecode/plate-indent-list and add @platejs/list.

@udecode/plate-juice

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-kbd

Breaking Changes

  • Package @udecode/plate-kbd has been deprecated. (#4327)
  • KbdPlugin has been moved to the @platejs/basic-nodes package.
  • Migration:
    • Remove @udecode/plate-kbd from your dependencies.
    • Add @platejs/basic-nodes to your dependencies if not already present.
    • Import KbdPlugin from @platejs/basic-nodes/react.

@udecode/plate-layout

Breaking Changes

  • Delete backward from a column start will merge into the previous column (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-line-height

Breaking Changes

  • Package @udecode/plate-line-height has been deprecated. (#4327)

    • LineHeightPlugin has been moved to the @platejs/basic-styles package.

    • Migration:

      • Remove @udecode/plate-line-height from your dependencies.
      • Add @platejs/basic-styles to your dependencies if not already present.
      • Import LineHeightPlugin from @platejs/basic-styles/react.
    • setLineHeight signature change:

    ts
    1// Before 2setLineHeight(editor, { value: 1.5, setNodesOptions }); 3 4// After 5setLineHeight(editor, 1.5, setNodesOptions);
    • Removed useLineHeightDropdownMenu and useLineHeightDropdownMenuState. Use it in your own codebase, for example:
    tsx
    1export function LineHeightToolbarButton() { 2 const editor = useEditorRef(); 3 const { defaultNodeValue, validNodeValues: values = [] } = 4 editor.getInjectProps(LineHeightPlugin); 5 6 const value = useSelectionFragmentProp({ 7 defaultValue: defaultNodeValue, 8 getProp: (node) => node.lineHeight, 9 }); 10 11 const onValueChange = (newValue: string) => { 12 editor.tf.lineHeight.setNodes(Number(newValue)); 13 editor.tf.focus(); 14 }; 15 16 // ... 17}

Features

  • New transform method to LineHeightPlugin: (#4327)
    • editor.tf.lineHeight.setNodes - Transform method for setting line height values. Alias to setLineHeight

@udecode/plate-link

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-list

Breaking Changes

  • The previous @udecode/plate-list (classic list implementation) has been moved to @platejs/list-classic. (#4327)

    • Migration for users of the classic list:
      • Rename all import paths from @udecode/plate-list to @platejs/list-classic.
      • Update your package.json: remove the old @udecode/plate-list (if it was a direct dependency) and add @platejs/list-classic.
  • This package, @platejs/list, now contains the functionality previously in @udecode/plate-indent-list (indent-based list system).

    • Plugin names have been generalized: IndentListPlugin is now ListPlugin, BaseIndentListPlugin is BaseListPlugin, etc. (*IndentList* -> *List*).
    • The primary plugin key is now list (e.g., ListPlugin.key) instead of listStyleType.
    • Constants for list keys previously in INDENT_LIST_KEYS are now available under KEYS from platejs.
      • Migration for constants:
        • INDENT_LIST_KEYS.listStyleType -> KEYS.listType
        • INDENT_LIST_KEYS.todo -> KEYS.listTodo
        • INDENT_LIST_KEYS.checked -> KEYS.listChecked
        • Other INDENT_LIST_KEYS.* map to KEYS.* accordingly.
    • Removed listStyleTypes option from ListPlugin. You should control list rendering via render.belowNodes instead.
    • Removed renderListBelowNodes.
  • For changelogs of the indent-based list system (now in this package) version <=48 (when it was @udecode/plate-indent-list), refer to its archived changelog.

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-list-classic

Breaking Changes

  • Removed Default Shortcuts for BulletedListPlugin and NumberedListPlugin. (#4327)
    • These shortcuts must now be configured manually using the shortcuts field.
    • Example:
      tsx
      1BulletedListPlugin.configure({ 2 shortcuts: { toggle: { keys: 'mod+alt+5' } }, 3}); 4NumberedListPlugin.configure({ 5 shortcuts: { toggle: { keys: 'mod+alt+6' } }, 6});
  • Package @udecode/plate-list has been moved to @platejs/list-classic.
    • Migration:
      • Rename all import paths from @udecode/plate-list to @platejs/list-classic.
      • Update your package.json: remove @udecode/plate-list and add @platejs/list-classic.
  • For changelogs of @udecode/plate-list version <=48, refer to its archived changelog.

@udecode/plate-markdown

Breaking Changes

  • Function indentListToMdastTree has been renamed to listToMdastTree to align with the list plugin renames (IndentListPlugin -> ListPlugin). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-math

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-media

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-mention

Breaking Changes

  • The type TMentionInputElement has been removed. (#4327)

  • Use TComboboxInputElement from @udecode/plate instead for input elements, as mention functionality is built upon the combobox.

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-node-id

Breaking Changes

  • Package @udecode/plate-node-id has been deprecated. (#4327)

  • NodeIdPlugin functionality is now part of @platejs/core and is enabled by default.

  • Migration:

    text
    1 - Remove `NodeIdPlugin` from your explicit plugin list if it was added manually. 2 3 - Remove `@udecode/plate-node-id` from your dependencies. 4 5 - If you had `NodeIdPlugin` configured with options, move these options to the `nodeId` field in your main editor configuration (`createPlateEditor` or `usePlateEditor` options). 6 Example: 7 8 ```ts 9 // Before 10 // const editor = usePlateEditor({ 11 // plugins: [ 12 // NodeIdPlugin.configure({ /* ...your options... */ }), 13 // ], 14 // }); 15 16 // After 17 const editor = usePlateEditor({ 18 nodeId: { 19 /* ...your options... */ 20 }, 21 // ...other editor options 22 }); 23 ``` 24 25 - If you want to disable automatic node ID generation (to replicate behavior if you weren't using `NodeIdPlugin` before), set `nodeId: false` in your editor configuration.

@udecode/plate-normalizers

Breaking Changes

  • Package @udecode/plate-normalizers has been deprecated. (#4327)
  • Its plugins have been moved to platejs (which is re-exported via platejs).
  • Migration:
    • Remove @udecode/plate-normalizers from your dependencies.
    • Update import paths to use platejs

@udecode/plate

Breaking Changes

  • Renamed package to platejs: (#4327)
    • Replace all @udecode/plate/react with platejs/react
    • Replace all '@udecode/plate' with 'platejs'

@udecode/plate-playwright

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-reset-node

Breaking Changes

  • Package @udecode/plate-reset-node has been deprecated. Its functionality (e.g., ResetNodePlugin) is now exclusively configured using the rules.break and rules.delete options on plugin definitions. Migration: (#4327)

    • Remove @udecode/plate-reset-node from your dependencies.
    • Remove any usage of ResetNodePlugin from your project.
    • Configure reset behaviors directly on the relevant plugins by defining rules.break and/or rules.delete.

    Example: Resetting a Blockquote to a Paragraph

    typescript
    1ResetNodePlugin.configure({ 2 options: { 3 rules: [ 4 { 5 types: [BlockquotePlugin.key], 6 defaultType: ParagraphPlugin.key, 7 hotkey: 'Enter', 8 predicate: (editor) => 9 editor.api.isEmpty(editor.selection, { block: true }), 10 }, 11 ], 12 }, 13}); 14 15// After 16BlockquotePlugin.configure({ 17 rules: { 18 break: { empty: 'reset' }, 19 delete: { start: 'reset' }, 20 }, 21});

    For custom reset logic (previously onReset):

    typescript
    1// Before 2ResetNodePlugin.configure({ 3 options: { 4 rules: [ 5 { 6 types: [CodeBlockPlugin.key], 7 defaultType: ParagraphPlugin.key, 8 hotkey: 'Enter', 9 predicate: isCodeBlockEmpty, 10 onReset: unwrapCodeBlock, 11 }, 12 ], 13 }, 14}); 15 16// After 17CodeBlockPlugin.configure({ 18 rules: { 19 delete: { empty: 'reset' }, 20 }, 21}).overrideEditor(({ editor, tf: { resetBlock } }) => ({ 22 transforms: { 23 resetBlock(options) { 24 if ( 25 editor.api.block({ 26 at: options?.at, 27 match: { type: editor.getType(CodeBlockPlugin.key) }, 28 }) 29 ) { 30 unwrapCodeBlock(editor); 31 return; 32 } 33 34 return resetBlock(options); 35 }, 36 }, 37}));

@udecode/plate-resizable

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-select

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Package @udecode/plate-select has been deprecated. (#4327)

  • SelectOnBackspacePlugin has been removed. This behavior is now built into Plate by default: delete (backward/forward) at the start of a block will select the previous/next void block instead of removing it.

  • DeletePlugin has been removed. This behavior is now built into Plate by default: delete (backward/forward) from an empty block will remove it instead of merging.

  • RemoveEmptyNodesPlugin has been removed. This behavior is now available through the rules: { normalize: { removeEmpty: true } } configuration on individual plugins.

  • Migration:

    • Remove @udecode/plate-select from your dependencies.
    • Remove any usage of SelectOnBackspacePlugin, DeletePlugin from your project.
    • Replace RemoveEmptyNodesPlugin.configure({ options: { types: ['custom'] } }) with CustomPlugin.configure({ rules: { normalize: { removeEmpty: true } } }). This is used by our LinkPlugin.

@udecode/plate-selection

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-slash-command

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

  • The type TSlashInputElement has been removed. (#4327)

  • Use TComboboxInputElement from platejs instead for Slash Command input elements, as slash command functionality is built upon the combobox.

@udecode/slate

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

  • Replaced editor.api.shouldMergeNodesRemovePrevNode with editor.api.shouldMergeNodes. shouldMergeNodes is now controlling the remove + merge behavior (#4327)

    text
    1 - Returns `true` if the default merging behavior should be applied. 2 - Returns `false` if the default merging behavior should not be applied. This is used by Plate to prevent void blocks deletion, and to prioritize empty block deletion over merging. 3 4 ```ts 5 // Before 6 editor.api.shouldMergeNodesRemovePrevNode(prev, current); 7 8 // After 9 editor.api.shouldMergeNodes(prev, current); 10 ```
    • Replace editor.api.fragment option structuralTypes with unwrap.

      ts
      1// Before 2editor.api.fragment(editor.selection, { structuralTypes: ['table'] }); 3 4// After 5editor.api.fragment(editor.selection, { unwrap: ['table'] });

Features

  • editor.tf.insertSoftBreak now inserts a soft break instead of a hard break. (#4327)

@udecode/plate-suggestion

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-tabbable

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-table

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-tag

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-test-utils

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-toc

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-toggle

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

@udecode/plate-trailing-block

Breaking Changes

  • The following plugins now default to editOnly: true. This means their core functionalities (handlers, rendering injections, etc.) will be disabled when the editor is in read-only mode. To override this behavior for a specific plugin, configure its editOnly field. For example, SomePlugin.configure({ editOnly: false }). (#4327)

  • Package @udecode/plate-trailing-block has been deprecated. (#4327)

  • Its functionality (e.g., TrailingBlockPlugin) has been moved to @platejs/utils (which is re-exported via platejs).

  • Migration:

    • Remove @udecode/plate-trailing-block from your dependencies.
    • Update import paths to use platejs (e.g., import { TrailingBlockPlugin } from 'platejs';).

@udecode/plate-utils

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

  • Node type definitions (e.g., TImageElement, TParagraphElement) previously co-located with their respective plugin packages (like @udecode/plate-media) have been centralized into @platejs/utils. These are typically re-exported via the main platejs package. (#4327)

    text
    1 - Migration: Update imports for these types to pull from `platejs`. 2 3 ```tsx 4 // Before 5 // import { TImageElement } from '@udecode/plate-media'; 6 7 // After 8 import { TImageElement } from 'platejs'; 9 ```
    • Removed structuralTypes option from useSelectionFragment and useSelectionFragmentProp. These hooks now automatically use plugin.node.isContainer from enabled plugins.

    • Removed:

      • createNodesHOC
      • createNodesWithHOC
      • createNodeHOC
    • Removed usePlaceholderState hook.

      • Migration: Use the BlockPlaceholderPlugin (typically from platejs) instead of the withPlaceholders HOC and usePlaceholderState. Configure placeholders directly within the BlockPlaceholderPlugin options.
        ts
        1// Example BlockPlaceholderPlugin configuration 2BlockPlaceholderPlugin.configure({ 3 options: { 4 className: 5 'before:absolute before:cursor-text before:opacity-30 before:content-[attr(placeholder)]', 6 placeholders: { 7 [ParagraphPlugin.key]: 'Type something...', 8 // ...other placeholders 9 }, 10 query: ({ editor, path }) => { 11 // Example query: only show for top-level empty blocks 12 return ( 13 path.length === 1 && editor.api.isEmpty(editor.children[path[0]]) 14 ); 15 }, 16 }, 17});

Features

  • New plugin SingleBlockPlugin to restrict editor content to a single block while preserving line breaks, while SingleLinePlugin prevents all line breaks. (#4327)

    • @platejs/utils (and by extension, platejs) now exports a comprehensive KEYS object containing all official plugin keys.

      • This is intended to improve decoupling and provide a centralized way to reference plugin keys.

      • Example Usage:

        ts
        1import { KEYS } from 'platejs'; 2 3// Instead of: ParagraphPlugin.key 4// Use: KEYS.p
    • Many node type definitions (e.g., TParagraphElement, TLinkElement) are also now exported from platejs, in addition to being available from their specific plugin packages if those still exist or from @platejs/basic-nodes.

@udecode/plate-yjs

Breaking Changes

  • Renamed all @udecode/plate-* packages to @platejs/*. Replace @udecode/plate- with @platejs/ in your code. (#4327)

CHANGELOG · v48.0.6...v49.0.0 · By @zbeyens