For older changelogs, see https://github.com/udecode/plate/blob/main/docs
@udecode/[email protected]
- #3920 by @zbeyens – AI plugins are now experimental: pin the dependency to avoid breaking changes. No breaking changes for this release.
@udecode/[email protected]
-
#3920 by @zbeyens – This package is now deprecated and will be renamed to
@udecode/plate
. Migration:- Remove
@udecode/plate-common
and install@udecode/plate
- Replace all
'@udecode/plate-common'
with'@udecode/plate'
,
- Remove
@udecode/[email protected]
-
-
Plugin
normalizeInitialValue
now returnsvoid
instead ofValue
. When mutating nodes, keep their references (e.g., useObject.assign
instead of spread). -
Editor methods have moved to
editor.tf
andeditor.api
. They still exist at the top level for slate backward compatibility, but are no longer redundantly typed. If you truly need the top-level method types, extend your editor type withLegacyEditorMethods
(e.g.editor as Editor & LegacyEditorMethods
). Since these methods can be overridden byextendEditor
,with...
, or slate plugins, consider migrating to the following approaches:// For overriding existing methods only: overrideEditor(({ editor, tf: { deleteForward }, api: { isInline } }) => ({ transforms: { deleteForward(options) { // ...conditional override deleteForward(options); }, }, api: { isInline(element) { // ...conditional override return isInline(element); }, }, }));
This was previously done in
extendEditor
using top-level methods, which still works but now throws a type error due to the move toeditor.tf/editor.api
. A workaround is to extend your editor withLegacyEditorMethods
.Why? Having all methods at the top-level (next to
children
,marks
, etc.) would clutter the editor interface. Slate splits transforms in three places (editor
,Editor
, andTransforms
), which is also confusing. We've reorganized them intotf
andapi
for better DX, but also to support transform-only middlewares in the future. This also lets us leverageextendEditorTransforms
,extendEditorApi
, andoverrideEditor
to modify those methods.Migration example:
// From: export const withInlineVoid: ExtendEditor = ({ editor }) => { const { isInline, isSelectable, isVoid, markableVoid } = editor; const voidTypes: string[] = []; const inlineTypes: string[] = []; editor.pluginList.forEach((plugin) => { if (plugin.node.isInline) { inlineTypes.push(plugin.node.type); } if (plugin.node.isVoid) { voidTypes.push(plugin.node.type); } }); editor.isInline = (element) => { return inlineTypes.includes(element.type as any) ? true : isInline(element); }; editor.isVoid = (element) => { return voidTypes.includes(element.type as any) ? true : isVoid(element); }; return editor; }; export const InlineVoidPlugin = createSlatePlugin({ key: 'inlineVoid', extendEditor: withInlineVoid, }); // After (using overrideEditor since we're only overriding existing methods): export const withInlineVoid: OverrideEditor = ({ api: { isInline, isSelectable, isVoid, markableVoid }, editor, }) => { const voidTypes: string[] = []; const inlineTypes: string[] = []; editor.pluginList.forEach((plugin) => { if (plugin.node.isInline) { inlineTypes.push(plugin.node.type); } if (plugin.node.isVoid) { voidTypes.push(plugin.node.type); } }); return { api: { isInline(element) { return inlineTypes.includes(element.type as any) ? true : isInline(element); }, isVoid(element) { return voidTypes.includes(element.type as any) ? true : isVoid(element); }, }, }; }; export const InlineVoidPlugin = createSlatePlugin({ key: 'inlineVoid', }).overrideEditor(withInlineVoid);
- Move
editor.redecorate
toeditor.api.redecorate
Types:
- Rename
TRenderElementProps
toRenderElementProps
- Rename
TRenderLeafProps
toRenderLeafProps
- Rename
TEditableProps
toEditableProps
-
@udecode/[email protected]
-
#3920 by @zbeyens – This package is now the new common package, so all plugin packages are being removed. Migration:
- Add the following dependencies:
"@udecode/plate-alignment": "42.0.0", "@udecode/plate-autoformat": "42.0.0", "@udecode/plate-basic-elements": "42.0.0", "@udecode/plate-basic-marks": "42.0.0", "@udecode/plate-block-quote": "42.0.0", "@udecode/plate-break": "42.0.0", "@udecode/plate-code-block": "42.0.0", "@udecode/plate-combobox": "42.0.0", "@udecode/plate-comments": "42.0.0", "@udecode/plate-csv": "42.0.0", "@udecode/plate-diff": "42.0.0", "@udecode/plate-docx": "42.0.0", "@udecode/plate-find-replace": "42.0.0", "@udecode/plate-floating": "42.0.0", "@udecode/plate-font": "42.0.0", "@udecode/plate-heading": "42.0.0", "@udecode/plate-highlight": "42.0.0", "@udecode/plate-horizontal-rule": "42.0.0", "@udecode/plate-indent": "42.0.0", "@udecode/plate-indent-list": "42.0.0", "@udecode/plate-kbd": "42.0.0", "@udecode/plate-layout": "42.0.0", "@udecode/plate-line-height": "42.0.0", "@udecode/plate-link": "42.0.0", "@udecode/plate-list": "42.0.0", "@udecode/plate-markdown": "42.0.0", "@udecode/plate-media": "42.0.0", "@udecode/plate-mention": "42.0.0", "@udecode/plate-node-id": "42.0.0", "@udecode/plate-normalizers": "42.0.0", "@udecode/plate-reset-node": "42.0.0", "@udecode/plate-resizable": "42.0.0", "@udecode/plate-select": "42.0.0", "@udecode/plate-selection": "42.0.0", "@udecode/plate-slash-command": "42.0.0", "@udecode/plate-suggestion": "42.0.0", "@udecode/plate-tabbable": "42.0.0", "@udecode/plate-table": "42.0.0", "@udecode/plate-toggle": "42.0.0", "@udecode/plate-trailing-block": "42.0.0"
- Either replace all
@udecode/plate
imports with the individual package imports, or export the following in a new file (e.g.src/plate.ts
):
export * from '@udecode/plate-alignment'; export * from '@udecode/plate-autoformat'; export * from '@udecode/plate-basic-elements'; export * from '@udecode/plate-basic-marks'; export * from '@udecode/plate-block-quote'; export * from '@udecode/plate-break'; export * from '@udecode/plate-code-block'; export * from '@udecode/plate-combobox'; export * from '@udecode/plate-comments'; export * from '@udecode/plate-diff'; export * from '@udecode/plate-find-replace'; export * from '@udecode/plate-font'; export * from '@udecode/plate-heading'; export * from '@udecode/plate-highlight'; export * from '@udecode/plate-horizontal-rule'; export * from '@udecode/plate-indent'; export * from '@udecode/plate-indent-list'; export * from '@udecode/plate-kbd'; export * from '@udecode/plate-layout'; export * from '@udecode/plate-line-height'; export * from '@udecode/plate-link'; export * from '@udecode/plate-list'; export * from '@udecode/plate-media'; export * from '@udecode/plate-mention'; export * from '@udecode/plate-node-id'; export * from '@udecode/plate-normalizers'; export * from '@udecode/plate-reset-node'; export * from '@udecode/plate-select'; export * from '@udecode/plate-csv'; export * from '@udecode/plate-docx'; export * from '@udecode/plate-markdown'; export * from '@udecode/plate-slash-command'; export * from '@udecode/plate-suggestion'; export * from '@udecode/plate-tabbable'; export * from '@udecode/plate-table'; export * from '@udecode/plate-toggle'; export * from '@udecode/plate-trailing-block'; export * from '@udecode/plate-alignment/react'; export * from '@udecode/plate-autoformat/react'; export * from '@udecode/plate-basic-elements/react'; export * from '@udecode/plate-basic-marks/react'; export * from '@udecode/plate-block-quote/react'; export * from '@udecode/plate-break/react'; export * from '@udecode/plate-code-block/react'; export * from '@udecode/plate-combobox/react'; export * from '@udecode/plate-comments/react'; export * from '@udecode/plate-floating'; export * from '@udecode/plate-font/react'; export * from '@udecode/plate-heading/react'; export * from '@udecode/plate-highlight/react'; export * from '@udecode/plate-layout/react'; export * from '@udecode/plate-slash-command/react'; export * from '@udecode/plate-indent/react'; export * from '@udecode/plate-indent-list/react'; export * from '@udecode/plate-kbd/react'; export * from '@udecode/plate-line-height/react'; export * from '@udecode/plate-link/react'; export * from '@udecode/plate-list/react'; export * from '@udecode/plate-media/react'; export * from '@udecode/plate-reset-node/react'; export * from '@udecode/plate-selection'; export * from '@udecode/plate-suggestion/react'; export * from '@udecode/plate-tabbable/react'; export * from '@udecode/plate-table/react'; export * from '@udecode/plate-toggle/react'; export * from '@udecode/plate-resizable';
- Replace all
'@udecode/plate'
and'@udecode/plate/react'
with'@/plate'
in your codebase.
@udecode/[email protected]
- #3920 by @zbeyens –
- Removed unused
moveSelectionByOffset
,getLastBlockDOMNode
,useLastBlock
,useLastBlockDOMNode
- Removed unused
@udecode/[email protected]
@udecode/[email protected]
-
- Remove
slate
,slate-dom
,slate-react
,slate-history
andslate-hyperscript
from your dependencies. It's now part of this package and@udecode/plate
. All exports remain the same or have equivalents (see below). - Renamed
createTEditor
tocreateEditor
. createEditor
now returns an editor (Editor
) with all queries undereditor.api
and transforms undereditor.tf
. You can see or override them at a glance. For example, we now useeditor.tf.setNodes
instead of importingsetNodes
. This marks the completion of generic typing and the removal of error throws fromslate
,slate-dom
, andslate-history
queries/transforms, without forking implementations. We’ve also reduced the number of queries/transforms by merging a bunch of them.
The following interfaces from
slate
andslate-dom
are now part ofEditor
:-
Editor
,EditorInterface
-
Transforms
-
HistoryEditor
(noop, unchanged),HistoryEditorInterface
-
DOMEditor
(noop, unchanged),DOMEditorInterface
-
editor.findPath
now returnsDOMEditor.findPath
(memo) and falls back tofindNodePath
(traversal, less performant) if not found. -
Removed the first parameter (
editor
) from:editor.hasEditableTarget
editor.hasSelectableTarget
editor.isTargetInsideNonReadonlyVoid
editor.hasRange
editor.hasTarget
-
editor.api.node(options)
(previouslyfindNode
)at
option is nowat ?? editor.selection
instead ofat ?? editor.selection ?? []
. That means if you want to lookup the entire document, you need to pass[]
explicitly. -
Removed
setNode
in favor ofsetNodes
(you can now pass aTNode
toat
directly). -
Removed
setElements
in favor ofsetNodes
. -
Removed unused
isWordAfterTrigger
,setBlockAboveNode
,setBlockAboveTexts
,setBlockNodes
,getPointNextToVoid
. -
Replaced
Path
from slate withPath
(type) andPathApi
(static methods). -
Replaced
Operation
from slate withOperation
(type) andOperationApi
(static methods). -
Replaced
Point
from slate withPoint
(type) andPointApi
(static methods). -
Replaced
Text
from slate withTText
(type) andTextApi
(static methods). We also exportText
type likeslate
but we don't recommend it as it's conflicting with the DOM type. -
Replaced
Range
from slate withTRange
(type) andRangeApi
(static methods). We also exportRange
type likeslate
but we don't recommend it as it's conflicting with the DOM type. -
Replaced
Location
from slate withTLocation
(type) andLocationApi
(static methods). We also exportLocation
type likeslate
but we don't recommend it as it's conflicting with the DOM type. -
Replaced
Span
from slate withSpan
(type) andSpanApi
(static methods). -
Replaced
Node
from slate withTNode
(type) andNodeApi
(static methods). We also exportNode
type likeslate
but we don't recommend it as it's conflicting with the DOM type. -
Replaced
Element
from slate withTElement
(type) andElementApi
(static methods). We also exportElement
type likeslate
but we don't recommend it as it's conflicting with the DOM type. -
Signature change:
editor.tf.toggle.block({ type, ...options })
->editor.tf.toggleBlock(type, options)
editor.tf.toggle.mark({ key, clear })
->editor.tf.toggleMark(key, { remove: clear })
-
Moved editor functions:
addMark
->editor.tf.addMark
addRangeMarks
->editor.tf.setNodes(props, { at, marks: true })
blurEditor
->editor.tf.blur
collapseSelection
->editor.tf.collapse
createDocumentNode
->editor.api.create.value
(core)createNode
->editor.api.create.block
createPathRef
->editor.api.pathRef
createPointRef
->editor.api.pointRef
createRangeRef
->editor.api.rangeRef
deleteBackward({ unit })
->editor.tf.deleteBackward(unit)
deleteForward({ unit })
->editor.tf.deleteForward(unit)
deleteFragment
->editor.tf.deleteFragment
deleteText
->editor.tf.delete
deselect
->editor.tf.deselect
deselectEditor
->editor.tf.deselectDOM
duplicateBlocks
->editor.tf.duplicateNodes({ nodes })
findDescendant
->editor.api.descendant
findEditorDocumentOrShadowRoot
->editor.api.findDocumentOrShadowRoot
findEventRange
->editor.api.findEventRange
findNode(options)
->editor.api.node(options)
findNodeKey
->editor.api.findKey
findNodePath
->editor.api.findPath
findPath
->editor.api.findPath
focusEditor
->editor.tf.focus({ at })
focusEditorEdge
->editor.tf.focus({ at, edge: 'startEditor' | 'endEditor' })
getAboveNode
->editor.api.above
getAncestorNode
->editor.api.block({ highest: true })
getBlockAbove
->editor.api.block({ at, above: true })
oreditor.api.block()
ifat
is not a pathgetBlocks
->editor.api.blocks
getEdgeBlocksAbove
->editor.api.edgeBlocks
getEdgePoints
->editor.api.edges
getEditorString
->editor.api.string
getEditorWindow
->editor.api.getWindow
getEndPoint
->editor.api.end
getFirstNode
->editor.api.first
getFragment
->editor.api.fragment
getFragmentProp(fragment, options)
->editor.api.prop({ nodes, ...options})
getLastNode
->editor.api.last
getLastNodeByLevel(level)
->editor.api.last([], { level })
getLeafNode
->editor.api.leaf
getLevels
->editor.api.levels
getMark
->editor.api.mark
getMarks
->editor.api.marks
getNextNode
->editor.api.next
getNextNodeStartPoint
->editor.api.start(at, { next: true })
getNodeEntries
->editor.api.nodes
getNodeEntry
->editor.api.node(at, options)
getNodesRange
->editor.api.nodesRange
getParentNode
->editor.api.parent
getPath
->editor.api.path
getPathRefs
->editor.api.pathRefs
getPoint
->editor.api.point
getPointAfter
->editor.api.after
getPointBefore
->editor.api.before
getPointBeforeLocation
->editor.api.before
getPointRefs
->editor.api.pointRefs
getPositions
->editor.api.positions
getPreviousBlockById
->editor.api.previous({ id, block: true })
getPreviousNode
->editor.api.previous
getPreviousNodeEndPoint
->editor.api.end({ previous: true })
getPreviousSiblingNode
->editor.api.previous({ at, sibling: true })
getRange
->editor.api.range
getRangeBefore
->editor.api.range('before', to, { before })
getRangeFromBlockStart
->editor.api.range('start', to)
getRangeRefs
->editor.api.rangeRefs
getSelectionFragment
->editor.api.fragment(editor.selection, { structuralTypes })
getSelectionText
->editor.api.string()
getStartPoint
->editor.api.start
getVoidNode
->editor.api.void
hasBlocks
->editor.api.hasBlocks
hasEditorDOMNode
->editor.api.hasDOMNode
hasEditorEditableTarget
->editor.api.hasEditableTarget
hasEditorSelectableTarget
->editor.api.hasSelectableTarget
hasEditorTarget
->editor.api.hasTarget
hasInlines
->editor.api.hasInlines
hasTexts
->editor.api.hasTexts
insertBreak
->editor.tf.insertBreak
insertData
->editor.tf.insertData
insertElements
->editor.tf.insertNodes<TElement>
insertEmptyElement
->editor.tf.insertNodes(editor.api.create.block({ type }))
insertFragment
->editor.tf.insertFragment
insertNode
->editor.tf.insertNode
insertNodes
->editor.tf.insertNodes
insertText
->editor.tf.insertText
isAncestorEmpty
->editor.api.isEmpty
isBlock
->editor.api.isBlock
isBlockAboveEmpty
->editor.api.isEmpty(editor.selection, { block: true })
isBlockTextEmptyAfterSelection
->editor.api.isEmpty(editor.selection, { after: true })
isCollapsed(editor.selection)
->editor.api.isCollapsed()
isComposing
->editor.api.isComposing
isDocumentEnd
->editor.api.isEditorEnd
isEdgePoint
->editor.api.isEdge
isEditor
->editor.api.isEditor
isEditorEmpty
->editor.api.isEmpty()
isEditorFocused
->editor.api.isFocused
isEditorNormalizing
->editor.api.isNormalizing
isEditorReadOnly
->editor.api.isReadOnly
isElementEmpty
->editor.api.isEmpty
isElementReadOnly
->editor.api.elementReadOnly
isEndPoint
->editor.api.isEnd
isExpanded(editor.selection)
->editor.api.isCollapsed()
isInline
->editor.api.isInline
isMarkableVoid
->editor.api.markableVoid
isMarkActive
->editor.api.hasMark(key)
isPointAtWordEnd
->editor.api.isAt({ at, word: true, end: true })
isRangeAcrossBlocks
->editor.api.isAt({ at, blocks: true })
isRangeInSameBlock
->editor.api.isAt({ at, block: true })
isRangeInSingleText
->editor.api.isAt({ at, text: true })
isSelectionAtBlockEnd
->editor.api.isAt({ end: true })
isSelectionAtBlockStart
->editor.api.isAt({ start: true })
isSelectionCoverBlock
->editor.api.isAt({ block: true, start: true, end: true })
isSelectionExpanded
->editor.api.isExpanded()
isStartPoint
->editor.api.isStart
isTargetinsideNonReadonlyVoidEditor
->editor.api.isTargetInsideNonReadonlyVoid
isTextByPath
->editor.api.isText(at)
isVoid
->editor.api.isVoid
liftNodes
->editor.tf.liftNodes
mergeNodes
->editor.tf.mergeNodes
moveChildren
->editor.tf.moveNodes({ at, to, children: true, fromIndex, match: (node, path) => boolean })
moveNodes
->editor.tf.moveNodes
moveSelection
->editor.tf.move
normalizeEditor
->editor.tf.normalize
removeEditorMark
->editor.tf.removeMark
removeEditorText
->editor.tf.removeNodes({ text: true, empty: false })
removeEmptyPreviousBlock
->editor.tf.removeNodes({ previousEmptyBlock: true })
removeMark(options)
->editor.tf.removeMarks(keys, options)
removeNodeChildren
->editor.tf.removeNodes({ at, children: true })
removeNodes
->editor.tf.removeNodes
removeSelectionMark
->editor.tf.removeMarks()
replaceNode(editor, { nodes, insertOptions, removeOptions })
->editor.tf.replaceNodes(nodes, { removeNodes, ...insertOptions })
select
->editor.tf.select
selectEndOfBlockAboveSelection
->editor.tf.select(editor.selection, { edge: 'end' })
selectNodes
->editor.tf.select(editor.api.nodesRange(nodes))
setFragmentData
->editor.tf.setFragmentData
setMarks(marks, clear)
->editor.tf.addMarks(marks, { remove: string | string[] })
setNodes
->editor.tf.setNodes
setPoint
->editor.tf.setPoint
setSelection
->editor.tf.setSelection
someNode
->editor.api.some(options)
splitNodes
->editor.tf.splitNodes
toDOMNode
->editor.api.toDOMNode
toDOMPoint
->editor.api.toDOMPoint
toDOMRange
->editor.api.toDOMRange
toggleWrapNodes
->editor.tf.toggleBlock(type, { wrap: true })
toSlateNode
->editor.api.toSlateNode
toSlatePoint
->editor.api.toSlatePoint
toSlateRange
->editor.api.toSlateRange
unhangCharacterRange
->editor.api.unhangRange(range, { character: true })
unhangRange
->editor.api.unhangRange
unsetNodes
->editor.tf.unsetNodes
unwrapNodes
->editor.tf.unwrapNodes
withoutNormalizing
->editor.tf.withoutNormalizing
wrapNodeChildren
->editor.tf.wrapNodes(element, { children: true })
wrapNodes
->editor.tf.wrapNodes
replaceNodeChildren
->editor.tf.replaceNodes({ at, children: true })
resetEditor
->editor.tf.reset
resetEditorChildren
->editor.tf.reset({ children: true })
selectEditor
->editor.tf.select([], { focus, edge })
selectSiblingNodePoint
->editor.tf.select(at, { next, previous })
-
Moved to
NodeApi.
:getNextSiblingNodes(parentEntry, path)
->NodeApi.children(editor, path, { from: path.at(-1) + 1 })
getFirstNodeText
->NodeApi.firstText
getFirstChild([node, path])
->NodeApi.firstChild(editor, path)
getLastChild([node, path])
->NodeApi.lastChild(editor, path)
getLastChildPath([node, path])
->NodeApi.lastChild(editor, path)
isLastChild([node, path], childPath)
->NodeApi.isLastChild(editor, childPath)
getChildren([node, path])
->Array.from(NodeApi.children(editor, path))
getCommonNode
->NodeApi.common
getNode
->NodeApi.get
getNodeAncestor
->NodeApi.ancestor
getNodeAncestors
->NodeApi.ancestors
getNodeChild
->NodeApi.child
getNodeChildren
->NodeApi.children
getNodeDescendant
->NodeApi.descendant
getNodeDescendants
->NodeApi.descendants
getNodeElements
->NodeApi.elements
getNodeFirstNode
->NodeApi.first
getNodeFragment
->NodeApi.fragment
getNodeLastNode
->NodeApi.last
getNodeLeaf
->NodeApi.leaf
getNodeLevels
->NodeApi.levels
getNodeParent
->NodeApi.parent
getNodeProps
->NodeApi.extractProps
getNodes
->NodeApi.nodes
getNodeString
->NodeApi.string
getNodeTexts
->NodeApi.texts
hasNode
->NodeApi.has
hasSingleChild
->NodeApi.hasSingleChild
isAncestor
->NodeApi.isAncestor
isDescendant
->NodeApi.isDescendant
isNode
->NodeApi.isNode
isNodeList
->NodeApi.isNodeList
nodeMatches
->NodeApi.matches
-
Moved to
ElementApi.
:elementMatches
->ElementApi.matches
isElement
->ElementApi.isElement
isElementList
->ElementApi.isElementList
-
Moved to
TextApi.
:isText
->TextApi.isText(at)
-
Moved to
RangeApi.
:isCollapsed
->RangeApi.isCollapsed
isExpanded
->RangeApi.isExpanded
-
Moved to
PathApi.
:isFirstChild
->!PathApi.hasPrevious
getPreviousPath
->PathApi.previous
-
Moved to
PointApi.
:getPointFromLocation({ at, focus })
->PointApi.get(at, { focus })
-
Moved from
@udecode/plate/react
to@udecode/plate
:Hotkeys
-
Upgraded to
zustand@5
andzustand-x@5
:- Replace
createZustandStore('name')(initialState)
withcreateZustandStore(initialState, { mutative: true, name: 'name' })
- All plugin stores now use zustand-mutative for immutable state updates, which is faster than
immer
.
- Replace
Types:
- Rename the following types:
TEditor
->Editor
TOperation
->Operation
TPath
->Path
TNodeProps
->NodeProps
TNodeChildEntry
->NodeChildEntry
TNodeEntry
->NodeEntry
TDescendant
->Descendant
TDescendantEntry
->DescendantEntry
TAncestor
->Ancestor
TAncestorEntry
->AncestorEntry
TElementEntry
->ElementEntry
TTextEntry
->TextEntry
- Query/transform options now use generic
V extends Value
instead ofE extends Editor
. getEndPoint
,getEdgePoints
,getFirstNode
,getFragment
,getLastNode
,getLeafNode
,getPath
,getPoint
,getStartPoint
can returnundefined
if not found (suppressing error throws).NodeApi.ancestor
,NodeApi.child
,NodeApi.common
,NodeApi.descendant
,NodeApi.first
,NodeApi.get
,NodeApi.last
,NodeApi.leaf
,NodeApi.parent
,NodeApi.getIf
,PathApi.previous
returnundefined
if not found instead of throwing- Replace
NodeOf
type withDescendantOf
ineditor.tf.setNodes
editor.tf.unsetNodes
,editor.api.previous
,editor.api.node
,editor.api.nodes
,editor.api.last
- Enhanced
editor.tf.setNodes
:- Added
marks
option to handle mark-specific operations - When
marks: true
:- Only applies to text nodes in non-void nodes or markable void nodes
- Automatically sets
split: true
andvoids: true
- Handles both expanded ranges and collapsed selections in markable voids
- Replaces
addRangeMarks
functionality
- Added
- Remove
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
-
#3920 by @zbeyens – Major performance improvement: all table cells were re-rendering when a single cell changed. This is now fixed.
TablePlugin
now depends onNodeIdPlugin
.- Table merging is now enabled by default:
- Renamed
enableMerging
todisableMerge
. - Migration:
enableMerging: true
→ remove the option.- otherwise →
TablePlugin.configure({ options: { disableMerge: true } })
- Renamed
- Renamed
unmergeTableCells
tosplitTableCell
. - Renamed
editor.api.create.cell
toeditor.api.create.tableCell
. - In
useTableMergeState
, renamedcanUnmerge
tocanSplit
. insertTableRow
andinsertTableColumn
: removeddisableSelect
in favor ofselect
. Migration: replace it with the opposite boolean.getTableCellBorders
: params(element, options)
→(editor, options)
; removedisFirstCell
andisFirstRow
.- Merged
useTableCellElementState
intouseTableCellElement
:- Removed its parameter.
- Removed
hovered
andhoveredLeft
returns (use CSS instead). - Renamed
rowSize
tominHeight
. - Computes column sizes and returns
width
.
- Merged
useTableCellElementResizableState
intouseTableCellElementResizable
:- Removed
onHover
andonHoverEnd
props (use CSS instead).
- Removed
- Merged
useTableElementState
intouseTableElement
:- Removed its parameter.
- No longer computes and returns
colSizes
,minColumnWidth
, andcolGroupProps
.
@udecode/[email protected]
-
#3830 by @felixfeng33 – Rename
findNodePath
tofindPath
since the addition offindNodePath
in the headless lib.We recommend using
findPath
mostly when subscribing to its value (e.g. in a React component) as it has O(path.length) complexity, compared to O(n) for the traversal-basedfindNodePath
. This optimization is particularly important in:- Render functions of Plate components where using
findNodePath
would increase the initial render time by O(n²) - Key press handlers where using
findNodePath
would increase the handling time by O(n)
where n is the number of nodes in the editor.
- Render functions of Plate components where using
@udecode/[email protected]
-
- Removed
useDndBlock
,useDragBlock
, anduseDropBlock
hooks in favor ofuseDndNode
,useDragNode
, anduseDropNode
. - Removed
DndProvider
anduseDraggableStore
. Drop line state is now managed byDndPlugin
as a single state objectdropTarget
containing bothid
andline
. useDropNode
: removedonChangeDropLine
anddropLine
options
Migration steps:
- Remove
DndProvider
from your draggable component (e.g.draggable.tsx
) - Replace
useDraggableStore
withuseEditorPlugin(DndPlugin).useOption
- Remove
useDraggableState
. Useconst { isDragging, previewRef, handleRef } = useDraggable
- Remove
useDraggableGutter
. SetcontentEditable={false}
to your gutter element - Remove
props
fromuseDropLine
. SetcontentEditable={false}
to your drop line element - Remove
withDraggable
,useWithDraggable
. UseDraggableAboveNodes
instead
- Removed
@udecode/[email protected]
- #3830 by @felixfeng33 –
- Move
render.belowNodes
fromIndentListPlugin
toBaseIndentListPlugin
. Props type forlistStyleTypes.liComponent
andlistStyleTypes.markerComponent
options is nowSlateRenderElementProps
instead ofPlateRenderElementProps
- Move
someIndentList
,someIndentTodo
from@udecode/plate-indent-list/react
to@udecode/plate-indent-list
- Move
@udecode/[email protected]
-
insertColumnGroup
: renamelayout
tocolumns
- Remove
setColumnWidth
,useColumnState
. UsesetColumns
instead
@udecode/[email protected]
-
#3830 by @felixfeng33 – Move from
@udecode/plate-table/react
to@udecode/plate-table
:deleteColumn
deleteColumnWhenExpanded
deleteRow
deleteRowWhenExpanded
getTableColumn
getTableGridAbove
getTableGridByRange
getTableRow
insertTable
mergeTableCells
moveSelectionFromCell
overrideSelectionFromCell
unmergeTableCells
withDeleteTable
withGetFragmentlable
withInsertFragmentTable
withInsertTextTable
withMarkTable
withSelectionTable
withSetFragmentDataTable
withTable
@udecode/[email protected]
- #3744 by @zbeyens –
- Add
slate-dom
as a peer dependency. - Update
slate-react
peer dependency to>=0.111.0
- Add
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3744 by @zbeyens –
- Remove
toggleColumns
in favor oftoggleColumnGroup
- Remove
insertEmptyColumn
in favor ofinsertColumn
- Remove
@udecode/[email protected]
-
#3597 by @zbeyens – The following changes were made to improve performance:
- Refactored
useDraggable
hook to focus on core dragging functionality:- Removed
dropLine
. UseuseDropLine().dropLine
instead. - Removed
groupProps
from the returned object –isHovered
, andsetIsHovered
from the returned state. Use CSS instead. - Removed
droplineProps
, andgutterLeftProps
from the returned object. UseuseDropLine().props
,useDraggableGutter().props
instead.
- Removed
- Refactored
@udecode/[email protected]
-
#3597 by @zbeyens – The following changes were made to improve performance:
- Removed
useHooksBlockSelection
in favor ofBlockSelectionAfterEditable
- Removed
slate-selected
class fromBlockSelectable
. You can do it on your components usinguseBlockSelected()
instead, or by using our newblock-selection.tsx
component. - Introduced
useBlockSelectableStore
for managing selectable state.
- Removed
@udecode/[email protected]
-
- Change
plugin.options
merging behavior from deep merge to shallow merge. - This affects
.extend()
,.configure()
, and other methods that modify plugin options. - This update addresses a performance regression introduced in v37 that affected editor creation.
Before:
const plugin = createSlatePlugin({ key: 'test', options: { nested: { a: 1 } }, }).extend({ options: { nested: { b: 1 } }, }); // Result: { nested: { a: 1, b: 1 } }
After:
const plugin = createSlatePlugin({ key: 'test', options: { nested: { a: 1 } }, }).extend(({ getOptions }) => ({ options: { ...getOptions(), nested: { ...getOptions().nested, b: 1 }, }, })); // Result: { nested: { a: 1, b: 1 } }
Migration:
- If you're using nested options and want to preserve the previous behavior, you need to manually spread both the top-level options and the nested objects.
- If you're not using nested options, no changes are required.
- Change
-
Rename all base plugins that have a React plugin counterpart to be prefixed with
Base
. This change improves clarity and distinguishes base implementations from potential React extensions. Use base plugins only for server-side environments or to extend your own DOM layer. -
Import the following plugins from
/react
entry:AlignPlugin
,CalloutPlugin
,EquationPlugin
,FontBackgroundColorPlugin
,FontColorPlugin
,FontFamilyPlugin
,FontSizePlugin
,FontWeightPlugin
,InlineEquationPlugin
,LineHeightPlugin
,TextIndentPlugin
,TocPlugin
Migration example: #3480
We recommend to upgrade to @udecode/[email protected]
in one-go.
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createBasicElementPlugins
->BasicElementsPlugin
createBlockquotePlugin
->BlockquotePlugin
createCodeBlockPlugin
->CodeBlockPlugin
createHeadingPlugin
->HeadingPlugin
- Move paragraph plugin to
@udecode/plate-core
@udecode/[email protected]
- #3420 by @zbeyens –
createBasicMarksPlugins
->BasicMarksPlugin
createBoldPlugin
->BoldPlugin
createCodePlugin
->CodePlugin
createItalicPlugin
->ItalicPlugin
createStrikethroughPlugin
->StrikethroughPlugin
createSubscriptPlugin
->SubscriptPlugin
createSuperscriptPlugin
->SuperscriptPlugin
createUnderlinePlugin
->UnderlinePlugin
- All mark plugins removed
hotkey
option. Useplugin.shortcuts
instead (see plate-core)
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createSoftBreakPlugin
->SoftBreakPlugin
createExitBreakPlugin
->ExitBreakPlugin
createSingleLinePlugin
->SingleLinePlugin
@udecode/[email protected]
- #3420 by @zbeyens –
createCaptionPlugin
->CaptionPlugin
CaptionPlugin
options:- Rename
pluginKeys
toplugins
- Rename
focusEndCaptionPath
tofocusEndPath
- Rename
focusStartCaptionPath
tofocusStartPath
- Rename
showCaptionId
tovisibleId
- Rename
isShow
toisVisible
- Rename
- Move
captionGlobalStore
toCaptionPlugin
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createCodeBlockPlugin
->CodeBlockPlugin
- NEW
CodeLinePlugin
- NEW
CodeSyntaxPlugin
- Remove
getCodeLineType
, useeditor.getType(CodeLinePlugin)
instead
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createCommentsPlugin
->CommentsPlugin
- Move
commentsStore
toCommentsPlugin
- Remove
CommentsProvider
and its hooks - Remove
useCommentsStates
(replaced by direct option access) - Remove
useCommentsSelectors
(replaced by option selectors) - Remove
useCommentsActions
(replaced by api methods) - Replace
useUpdateComment
withapi.comment.updateComment
- Replace
useAddRawComment
withapi.comment.addRawComment
- Replace
useAddComment
withapi.comment.addComment
- Replace
useRemoveComment
withapi.comment.removeComment
- Replace
useResetNewCommentValue
withapi.comment.resetNewCommentValue
- Replace
useNewCommentText
withoptions.newText
- Replace
useMyUser
withoptions.myUser
- Replace
useUserById
withoptions.userById
- Replace
useCommentById
withoptions.commentById
- Replace
useActiveComment
withoptions.activeComment
- Replace
useAddCommentMark
withinsert.comment
@udecode/[email protected]
- #3420 by @zbeyens –
- Split build into
@udecode/plate-common
and@udecode/plate-common/react
. - NEW
/react
exports@udecode/react-hotkeys
- Split build into
@udecode/[email protected]
-
#3420 by @zbeyens – Plugin System:
Decoupling React in all packages:
- Split build into
@udecode/plate-core
and@udecode/plate-core/react
- NEW
SlatePlugin
as the foundation for all plugins PlatePlugin
extendsSlatePlugin
with React-specific plugin features
Plugin Creation:
- Remove
createPluginFactory
- NEW
createSlatePlugin
: vanilla - NEW
createTSlatePlugin
: vanilla explicitly typed - NEW
createPlatePlugin
: React - NEW
createTPlatePlugin
: React explicitly typed - NEW
toPlatePlugin
: extend a vanilla plugin into a React plugin - NEW
toTPlatePlugin
: extend a vanilla plugin into a React plugin explicitly typed - Rename all plugins starting with
createNamePlugin()
toNamePlugin
Before:
const MyPluginFactory = createPluginFactory({ key: 'myPlugin', isElement: true, component: MyComponent, }); const plugin = MyPluginFactory();
After:
const plugin = createSlatePlugin({ key: 'myPlugin', node: { isElement: true, component: MyComponent, }, }); const reactPlugin = toPlatePlugin(plugin);
Plugin Configuration:
- Remove all
NamePlugin
option types, useNameConfig
instead. NameConfig
as the new naming convention for plugin configurations.
Before:
createPluginFactory<HotkeyPlugin>({ handlers: { onKeyDown: onKeyDownToggleElement, }, options: { hotkey: ['mod+opt+0', 'mod+shift+0'], }, });
After:
export const ParagraphPlugin = createPlatePlugin({ key: 'p', node: { isElement: true }, }).extend({ editor, type }) => ({ shortcuts: { toggleParagraph: { handler: () => { editor.tf.toggle.block({ type }); }, keys: [ [Key.Mod, Key.Alt, '0'], [Key.Mod, Key.Shift, '0'], ], preventDefault: true, }, }, })
toggleParagraph
is now a shortcut foreditor.tf.toggle.block({ type: 'p' })
for the given keys- Multiple shortcuts can be defined per plugin, and any shortcut can be disabled by setting
shortcuts.toggleParagraph = null
- Note the typing support using
Key
Plugin Properties:
Rename
SlatePlugin
/PlatePlugin
properties:type
->node.type
isElement
->node.isElement
isLeaf
->node.isLeaf
isInline
->node.isInline
isMarkableVoid
->node.isMarkableVoid
isVoid
->node.isVoid
component
->node.component
orrender.node
props
->node.props
overrideByKey
->override.plugins
renderAboveEditable
->render.aboveEditable
renderAboveSlate
->render.aboveSlate
renderAfterEditable
->render.afterEditable
renderBeforeEditable
->render.beforeEditable
inject.props
->inject.nodeProps
inject.props.validTypes
->inject.targetPlugins
inject.aboveComponent
->render.aboveNodes
inject.belowComponent
->render.belowNodes
inject.pluginsByKey
->inject.plugins
editor.insertData
->parser
- NEW
parser.format
now supportsstring[]
- NEW
parser.mimeTypes: string[]
- NEW
deserializeHtml
->parsers.html.deserializer
deserializeHtml.getNode
->parsers.html.deserializer.parse
serializeHtml
->parsers.htmlReact.serializer
withOverride
->extendEditor
- All methods now have a single parameter:
SlatePluginContext<C>
orPlatePluginContext<C>
, in addition to the method specific options. Some of the affected methods are:decorate
handlers
, includingonChange
. Returns({ event, ...ctx }) => void
instead of(editor, plugin) => (event) => void
handlers.onChange
:({ value, ...ctx }) => void
instead of(editor, plugin) => (value) => void
normalizeInitialValue
editor.insertData.preInsert
editor.insertData.transformData
editor.insertData.transformFragment
deserializeHtml.getNode
deserializeHtml.query
inject.props.query
inject.props.transformProps
useHooks
withOverrides
NEW
SlatePlugin
properties:api
: API methods provided by this plugindependencies
: An array of plugin keys that this plugin depends onnode
: Node-specific configuration for this pluginparsers
: Now acceptstring
keys to add custom parserspriority
: Plugin priority for registration and execution ordershortcuts
: Plugin-specific hotkeysinject.targetPluginToInject
: Function to inject plugin config into other plugins specified byinject.targetPlugins
Before:
export const createAlignPlugin = createPluginFactory({ key: KEY_ALIGN, inject: { props: { defaultNodeValue: 'start', nodeKey: KEY_ALIGN, styleKey: 'textAlign', validNodeValues: ['start', 'left', 'center', 'right', 'end', 'justify'], validTypes: ['p'], }, }, then: (_, plugin) => mapInjectPropsToPlugin(editor, plugin, { deserializeHtml: { getNode: (el, node) => { if (el.style.textAlign) { node[plugin.key] = el.style.textAlign; } }, }, }), });
After:
export const AlignPlugin = createSlatePlugin({ inject: { nodeProps: { defaultNodeValue: 'start', nodeKey: 'align', styleKey: 'textAlign', validNodeValues: ['start', 'left', 'center', 'right', 'end', 'justify'], }, targetPluginToInject: ({ editor, plugin }) => ({ parsers: { html: { deserializer: { parse: ({ element, node }) => { if (element.style.textAlign) { node[editor.getType(plugin)] = element.style.textAlign; } }, }, }, }, }), targetPlugins: [ParagraphPlugin.key], }, key: 'align', });
Plugin Shortcuts:
- NEW
shortcuts
to add custom hotkeys to a plugin. - Remove
hotkey
option from all plugins
Before:
type LinkPlugin = { hotkey?: string; };
After:
type LinkConfig = PluginConfig< // key 'p', // options { defaultLinkAttributes?: any }, // api { link: { getAttributes: (editor: PlateEditor) => LinkAttributes } }, // transforms { floatingLink: { hide: () => void } } >;
Shortcuts API:
handler
is called with the editor, event, and event details.keys
is an array of keys to trigger the shortcut.priority
is the priority of the shortcut over other shortcuts....HotkeysOptions
from@udecode/react-hotkeys
Plugin Types:
- Update
SlatePlugin
,PlatePlugin
generics.P, V, E
->C extends AnyPluginConfig = PluginConfig
- Remove
PluginOptions
- Remove
PlatePluginKey
- Remove
HotkeyPlugin
,ToggleMarkPlugin
in favor ofplugin.shortcuts
WithPlatePlugin
->EditorPlugin
,EditorPlatePlugin
PlatePluginComponent
->NodeComponent
InjectComponent*
->NodeWrapperComponent*
PlatePluginInsertData
->Parser
PlatePluginProps
->NodeProps
RenderAfterEditable
->EditableSiblingComponent
WithOverride
->ExtendEditor
SerializeHtml
->HtmlReactSerializer
Plugin Store:
- NEW each plugin has its own store, accessible via
plugin.optionsStore
andplugin.useOptionsStore
editor
has many methods to get, set and subscribe to plugin options
Plugin Methods:
- All plugin methods return a new plugin instance with the extended types.
- Remove
then
, useextend
instead - NEW
extend
method to deep merge a plugin configuration- If you pass an object, it will be directly merged with the plugin config.
- If you pass a function, it will be called with the plugin config once the editor is resolved and should return the new plugin config.
- Object extensions always have the priority over function extensions.
- Extend multiple times to derive from the result of the previous extension.
- NEW
configure
method to configure the properties of existing plugins. The difference withextend
is thatconfigure
with not add new properties to the plugin, it will only modify existing ones. - NEW
extendPlugin
method to extend a nested plugin configuration. - NEW
configurePlugin
method to configure the properties of a nested plugin. - NEW
extendApi
method to extend the plugin API. The API is then merged intoeditor.api[plugin.key]
. - NEW
extendTransforms
method to extend the plugin transforms. The transforms is then merged intoeditor.transforms[plugin.key]
. - NEW
extendEditorApi
method to extend the editor API. The API is then merged intoeditor.api
. Use this to add or override top-level methods to the editor. - NEW
extendEditorTransforms
method to extend the editor transforms. The transforms is then merged intoeditor.transforms
. - NEW
extendOptions
method to extend the plugin options with selectors. Useeditor.useOption(plugin, 'optionKey')
to subscribe to an (extended) option. - NEW
withComponent
to replaceplugin.node.component
Plugin Context
Each plugin method now receive the plugin context created with
getEditorPlugin(editor, plugin)
as parameter:api
editor
getOption
getOptions
plugin
setOption
setOptions
tf
type
useOption
Core Plugins:
- NEW
ParagraphPlugin
is now part ofcore
- NEW
DebugPlugin
is now part ofcore
- NEW
api.debug.log
,api.debug.info
,api.debug.warn
,api.debug.error
methods options.isProduction
to control logging in production environmentsoptions.logLevel
to set the minimum log leveloptions.logger
to customize logging behavioroptions.throwErrors
to control error throwing behavior, by default aPlateError
will be thrown onapi.debug.error
- NEW
- NEW - You can now override a core plugin by adding it to
editor.plugins
. Last plugin wins. createDeserializeHtmlPlugin
->HtmlPlugin
- NEW
api.html.deserialize
- NEW
createEventEditorPlugin
->EventEditorPlugin
eventEditorStore
->EventEditorStore
createDeserializeAstPlugin
->AstPlugin
createEditorProtocolPlugin
->SlateNextPlugin
- NEW
editor.tf.toggle.block
- NEW
editor.tf.toggle.mark
- Remove
createNodeFactoryPlugin
, included inSlateNextPlugin
. - Remove
createPrevSelectionPlugin
, included inSlateNextPlugin
.
- NEW
createHistoryPlugin
->HistoryPlugin
createInlineVoidPlugin
->InlineVoidPlugin
createInsertDataPlugin
->ParserPlugin
createLengthPlugin
->LengthPlugin
createReactPlugin
->ReactPlugin
Editor Creation:
NEW
withSlate
:- Extends an editor into a vanilla Plate editor
- NEW
rootPlugin
option for configuring the root plugin
NEW
withPlate
:- Extends an editor into a React Plate editor
- Now extends
withSlate
with React-specific enhancements - NEW
useOptions
anduseOption
methods to the editor
NEW
createSlateEditor
:- Create a vanilla Plate editor with server-side support
createPlateEditor
:-
Plugin replacement mechanism: using
plugins
, any plugin with the same key that a previous plugin will replace it. That means you can now override core plugins that way, likeReactPlugin
-
root
plugin is now created fromcreatePlateEditor
option as a quicker way to configure the editor than passingplugins
. Since plugins can have nested plugins (think as a recursive tree),plugins
option will be passed toroot
pluginplugins
option. -
Centralized editor resolution. Before, both
createPlateEditor
andPlate
component were resolving the editor. Now, onlycreatePlateEditor
takes care of that. That meansid
,value
, and other options are now controlled bycreatePlateEditor
. -
Remove
createPlugins
, pass plugins directly:components
->override.components
overrideByKey
->override.plugins
createPlateEditor
options:- Rename
normalizeInitialValue
option toshouldNormalizeEditor
- Move
components
tooverride.components
to override components by key - Move
overrideByKey
tooverride.plugins
to override plugins by key - Remove
disableCorePlugins
, useoverride.enabled
instead - NEW
value
to set the initial value of the editor. - NEW
autoSelect?: 'end' | 'start' | boolean
to auto select the start of end of the editor. This is decoupled fromautoFocus
. - NEW
selection
to control the initial selection. - NEW
override.enabled
to disable plugins by key - NEW
rootPlugin?: (plugin: AnyPlatePlugin) => AnyPlatePlugin
to configure the root plugin. From here, you can for example callconfigurePlugin
to configure any plugin. - NEW
api
,decorate
,extendEditor
,handlers
,inject
,normalizeInitialValue
,options
,override
,priority
,render
,shortcuts
,transforms
,useHooks
. These options will be passed to the very firstrootPlugin
.
NEW
usePlateEditor()
hook to create aPlateEditor
in a React component:- Uses
createPlateEditor
anduseMemo
to avoid re-creating the editor on every render. - Dependencies can be added to the hook to re-create the editor on demand.
id
option is always used as dependency.
Editor Methods:
editor: PlateEditor
:- Move
redecorate
toeditor.api.redecorate
- Move
reset
toeditor.tf.reset
- Move
plate.set
toeditor.setPlateState
- Move
blockFactory
toeditor.api.create.block
- Move
childrenFactory
toeditor.api.create.value
- Rename
plugins
topluginList
- Rename
pluginsByKey
toplugins
- NEW
getApi()
to get the editor API - NEW
getTransforms()
to get the editor transforms - Remove
getPlugin(editor, key)
, useeditor.getPlugin(plugin) or editor.getPlugin({ key })
- Remove
getPluginType
, useeditor.getType(plugin)
to get node type - Remove
getPluginInjectProps(editor, key)
, useeditor.getPlugin(plugin).inject.props
- NEW
getOptionsStore()
to get a plugin options store - Remove
getPluginOptions
, usegetOptions()
- NEW
getOption()
to get a plugin option - NEW
setOption()
to set a plugin option - NEW
setOptions()
to set multiple plugin options. Pass a function to use Immer. Pass an object to merge the options. - NEW
useOption
to subscribe to a plugin option in a React component - NEW
useOptions
to subscribe to a plugin options store in a React component - Remove
getPlugins
, useeditor.pluginList
- Remove
getPluginsByKey
, useeditor.plugins
- Remove
mapInjectPropsToPlugin
Editor Types:
The new generic types are:
V extends Value = Value
,P extends AnyPluginConfig = PlateCorePlugin
- That means this function will infer all plugin configurations from the options passed to it:
key
options
api
transforms
- Can't infer for some reason? Use
createTPlateEditor
for explicit typing.
const editor = createPlateEditor({ plugins: [TablePlugin] }); editor.api.htmlReact.serialize(); // core plugin is automatically inferred editor.tf.insert.tableRow(); // table plugin is automatically inferred
Plate Component
PlateProps
:editor
is now required. Ifnull
,Plate
will not render anything. As before,Plate
remounts onid
change.- Remove
id
,plugins
,maxLength
, pass these tocreatePlateEditor
instead - Remove
initialValue
,value
, passvalue
tocreatePlateEditor
instead - Remove
editorRef
- Remove
disableCorePlugins
, overrideplugins
increatePlateEditor
instead
Utils:
- Remove
useReplaceEditor
sinceeditor
is now always controlled - NEW
useEditorPlugin
to get the editor and the plugin context.
Types:
PlateRenderElementProps
,PlateRenderLeafProps
generics:V, N
->N, C
Plate Store:
- Remove
plugins
andrawPlugins
, useuseEditorRef().plugins
instead, or listen to plugin changes witheditor.useOption(plugin, <optionKey>)
- Remove
value
, useuseEditorValue()
instead - Remove
editorRef
, useuseEditorRef()
instead
Miscellaneous Changes
slate >=0.103.0
peer dependencyslate-react >=0.108.0
peer dependency- New dependency
@udecode/react-hotkeys
- Remove
ELEMENT_
,MARK_
andKEY_
constants. UseNamePlugin.key
instead. - Replace
ELEMENT_DEFAULT
withParagraphPlugin.key
. - Remove
getTEditor
- Rename
withTReact
towithPlateReact
- Rename
withTHistory
towithPlateHistory
- Rename
usePlateId
touseEditorId
- Remove
usePlateSelectors().id()
,usePlateSelectors().value()
,usePlateSelectors().plugins()
, use insteaduseEditorRef().<key>
- Rename
toggleNodeType
totoggleBlock
toggleBlock
options:- Rename
activeType
totype
- Rename
inactiveType
todefaultType
- Rename
- Remove
react-hotkeys-hook
re-exports. Use@udecode/react-hotkeys
instead.
Types:
- Move
TEditableProps
,TRenderElementProps
to@udecode/slate-react
- Remove
<V extends Value>
generic in all functions where not used - Remove
PlatePluginKey
- Remove
OverrideByKey
- Remove
PlateId
- Split build into
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createDndPlugin
->DndPlugin
- Remove
editor.isDragging
, useeditor.getOptions(DndPlugin).isDragging
instead - Move
dndStore
toDndPlugin
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createFontBackgroundColorPlugin
->FontBackgroundColorPlugin
createFontColorPlugin
->FontColorPlugin
createFontSizePlugin
->FontSizePlugin
createFontFamilyPlugin
->FontFamilyPlugin
createFontWeightPlugin
->FontWeightPlugin
@udecode/[email protected]
- #3420 by @zbeyens –
createHeadingPlugin
->HeadingPlugin
- Replace
ELEMENT_H1
withHEADING_KEYS.H1
- Replace
KEYS_HEADING
withHEADING_LEVELS
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createDeserializeHtmlPlugin
->HtmlPlugin
- Rename
deserializeHtml
plugin tohtml
- Rename
deserializeHtml.getNode
toparse
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createIndentListPlugin
->IndentListPlugin
- Rename
injectIndentListComponent
torenderIndentListBelowNodes
- Replace
normalizeIndentList
withwithNormalizeIndentList
- Replace
deleteBackwardIndentList
withwithDeleteBackwardIndentList
- Replace
insertBreakIndentList
withwithInsertBreakIndentList
- Remove types:
LiFC
(usePlateRenderElementProps
),MarkerFC
(useOmit<PlateRenderElementProps, 'children'>
)
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createListPlugin
->ListPlugin
- NEW
BulletedListPlugin
- NEW
NumberedListPlugin
- NEW
ListItemPlugin
- NEW
ListItemContentPlugin
- NEW list transforms:
toggle.list
,toggle.bulletedList
,toggle.numberedList
- Remove type utils:
getListItemType
,getUnorderedListType
,getOrderedListType
,getListItemContentType
- Replace
insertBreakList(editor)
withwithInsertBreakList(ctx)
- Replace
insertFragmentList(editor)
withwithInsertFragmentList(ctx)
- Replace
insertBreakTodoList(editor)
withwithInsertBreakTodoList(ctx)
- Replace
deleteForwardList(editor)
withwithdeleteForwardList(ctx)
- Replace
deleteBackwardList(editor)
withwithdeleteBackwardList(ctx)
- Move list options from
ul
andol
tolist
plugin toggleList
options are now{ type: string }
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createMediaPlugin
->MediaPlugin
FloatingMediaUrlInput
,submitFloatingMedia
rename optionpluginKey
->plugin
insertMediaEmbed
removekey
option
@udecode/[email protected]
- #3420 by @zbeyens –
createMentionPlugin
->MentionPlugin
- NEW
MentionInputPlugin
- Remove
createMentionNode
option, overrideapi.insert.mention
instead
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
- NEW
@udecode/plate-layout
- NEW
/react
exports@udecode/react-hotkeys
- Split build into
@udecode/plate
and@udecode/plate/react
. - Remove
@udecode/plate-paragraph
- All stores now start with a capital letter
- NEW
@udecode/[email protected]
- #3420 by @zbeyens –
- Remove
onKeyDownToggleElement
, use shortcuts instead. - Remove
onKeyDownToggleMark
, use shortcuts instead.
- Remove
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
@udecode/[email protected]
- #3420 by @zbeyens –
createSelectOnBackspacePlugin
->SelectOnBackspacePlugin
createDeletePlugin
->DeletePlugin
@udecode/[email protected]
- #3420 by @zbeyens –
- Rename
createSelectionPlugin
toBlockSelectionPlugin
- Remove
isNodeBlockSelected
,isBlockSelected
,hasBlockSelected
,useBlockSelected
functions- Use
editor.getOptions(BlockSelectionPlugin)
oreditor.useOptions(BlockSelectionPlugin)
instead
- Use
- Remove
addSelectedRow
function- Use
editor.api.blockSelection.addSelectedRow
instead
- Use
- Remove
withSelection
HOC - Rename
onCloseBlockSelection
toonChangeBlockSelection
- Moved
blockSelectionStore
toBlockSelectionPlugin
- Moved
blockContextMenuStore
toBlockContextMenuPlugin
- Remove
BlockStartArea
andBlockSelectionArea
components- Use
areaOptions
inBlockSelectionPlugin
for configuration instead
- Use
- Remove dependency on
@viselect/vanilla
package- Forked and integrated selection functionality locally
- Add
BlockContextMenuPlugin
, which is now used byBlockSelectionPlugin
- No need to add it manually
- Fix scroll-related bugs in the selection functionality
- Improve performance and reliability of block selection
- Rename
@udecode/[email protected]
@udecode/[email protected]
-
#3420 by @zbeyens –
createTEditor
:- Implement default methods for
slate-react
andslate-history
increateTEditor
- Add
noop
function to provide default implementations for unimplemented editor methods
Types:
- Merge
ReactEditor
andHistoryEditor
interfaces intoTEditor
, removingTReactEditor
andTHistoryEditor
- Remove
Value
generic type parameter from function signatures and type definitions - Replace
V extends Value
withE extends TEditor
for improved type inference - Simplify
TEditor<V>
toTEditor
in many places - Refactor element-related types, where
E extends TEditor
in all cases:EElement<V>
toElementOf<E>
EText<V>
toTextOf<E>
ENode<V>
toNodeOf<E>
EDescendant<V>
toDescendantOf<E>
EAncestor<V>
toAncestorOf<E>
EElementOrText<V>
toElementOrTextOf<E>
- Update
TNodeEntry
related types:ENodeEntry<V>
toNodeEntryOf<E>
EElementEntry<V>
toElementEntryOf<E>
ETextEntry<V>
toTextEntryOf<E>
EAncestorEntry<V>
toAncestorEntryOf<E>
EDescendantEntry<V>
toDescendantEntryOf<E>
- Remove unused types:
EElementEntry<V>
ETextEntry<V>
EDescendantEntry<V>
- Implement default methods for
@udecode/[email protected]
-
- Remove
TReactEditor
type, as it's now integrated into the mainTEditor
type in@udecode/slate
. UseTEditor
instead. - Replace
V extends Value
withE extends TEditor
for improved type inference - NEW
TEditableProps
,TRenderElementProps
- Remove
@udecode/[email protected]
-
- Replace
V extends Value
withE extends TEditor
for improved type inference
- Replace
@udecode/[email protected]
- #3420 by @zbeyens –
createSuggestionPlugin
->SuggestionPlugin
- Move
suggestionStore
toSuggestionPlugin
- Remove
SuggestionProvider
and its hooks - Remove
useSuggestionStates
(replaced by direct option access) - Remove
useSuggestionSelectors
(replaced by option selectors) - Remove
useSuggestionActions
(replaced by api methods) - Replace
useUpdateSuggestion
withapi.suggestion.updateSuggestion
- Replace
useAddSuggestion
withapi.suggestion.addSuggestion
- Replace
useRemoveSuggestion
withapi.suggestion.removeSuggestion
- Replace
useSuggestionById
withoptions.suggestionById
- Replace
useSuggestionUserById
withoptions.suggestionUserById
- Replace
useCurrentSuggestionUser
withoptions.currentSuggestionUser
- Remove
editor.activeSuggestionId
, use plugin option - Remove
useSetIsSuggesting
, useeditor.setOption
- Remove
useSetActiveSuggestionId
, useeditor.setOption
- Remove
editor.isSuggesting
, use plugin option - Remove
SuggestionEditorProps
type
@udecode/[email protected]
- #3420 by @zbeyens –
createTabbablePlugin
->TabbablePlugin
TabbablePlugin
optionisTabbable
: remove firsteditor
parameter
@udecode/[email protected]
- #3420 by @zbeyens –
createTablePlugin
->TablePlugin
- NEW
TableRowPlugin
,TableCellPlugin
,TableCellHeaderPlugin
- Replace
insertTableColumn
witheditor.insert.tableColumn
- Replace
insertTableRow
witheditor.insert.tableRow
- Move
cellFactory
option tocreate.cell
api - Move
getCellChildren
option totable.getCellChildren
api
@udecode/[email protected]
- #3420 by @zbeyens –
createTogglePlugin
->TogglePlugin
- Move
toggleControllerStore
toTogglePlugin
- Remove
setOpenIds
option - Replace
isToggleOpen
with optionisOpen
- Rename
injectToggle
torenderToggleAboveNodes