'use client';
import * as React from 'react';
import { Plate, usePlateEditor } from 'platejs/react';
import { EditorKit } from '@/components/editor/editor-kit';
import { Editor, EditorContainer } from '@/components/ui/editor';
import { DEMO_VALUES } from './values/demo-values';
export default function Demo({ id }: { id: string }) {
const editor = usePlateEditor({
plugins: EditorKit,
value: DEMO_VALUES[id],
});
return (
<Plate editor={editor}>
<EditorContainer variant="demo">
<Editor />
</EditorContainer>
</Plate>
);
}
The Block Selection feature allows users to select and manipulate entire text blocks, as opposed to individual words or characters.
Features
- Select entire blocks with a single action.
- Multi-block selection using mouse drag or keyboard shortcuts.
- Copy, cut, and delete operations on selected blocks.
- Keyboard shortcuts for quick selection:
Cmd+A
: Select all blocks.- Arrow keys: Select the block above or below.
- Customizable styling for selected blocks.
Kit Usage
Installation
The fastest way to add Block Selection is with the BlockSelectionKit
, which includes the pre-configured BlockSelectionPlugin
and the BlockSelection
UI component.
'use client';
import { BlockSelectionPlugin } from '@platejs/selection/react';
import { getPluginTypes, KEYS } from 'platejs';
import { BlockSelection } from '@/components/ui/block-selection';
export const BlockSelectionKit = [
BlockSelectionPlugin.configure(({ editor }) => ({
options: {
enableContextMenu: true,
isSelectable: (element) => {
return !getPluginTypes(editor, [
KEYS.column,
KEYS.codeLine,
KEYS.table,
KEYS.td,
]).includes(element.type);
},
},
render: {
belowRootNodes: (props) => {
if (!props.attributes.className?.includes('slate-selectable'))
return null;
return <BlockSelection {...(props as any)} />;
},
},
})),
];
BlockSelection
: Renders the selection rectangle around selected blocks.
Add Kit
The BlockSelectionKit
enables the context menu by default and provides a default isSelectable
logic to exclude common non-selectable blocks like code lines and table cells.
import { createPlateEditor } from 'platejs/react';
import { BlockSelectionKit } from '@/components/editor/plugins/block-selection-kit';
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
...BlockSelectionKit,
],
});
Manual Usage
Installation
pnpm add @platejs/selection
Add Plugin
import { BlockSelectionPlugin } from '@platejs/selection/react';
import { createPlateEditor } from 'platejs/react';
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
BlockSelectionPlugin,
],
});
Put this plugin before any other plugins overriding selectAll
– Cmd+A
(code block, table, column, etc.) to avoid any conflicts.
Excluding Blocks from Selection
You can control which blocks are selectable using options.isSelectable
. This function receives an element and its path, and should return true
if the block is selectable.
For example, to exclude code lines, columns, and table cells:
import { BlockSelectionPlugin } from '@platejs/selection/react';
BlockSelectionPlugin.configure({
options: {
isSelectable: (element, path) => {
if (['code_line', 'column', 'td'].includes(element.type)) {
return false;
}
// Exclude blocks inside table rows
if (editor.api.block({ above: true, at: path, match: { type: 'tr' } })) {
return false;
}
return true;
},
},
});
Customizing Scroll Behavior
If your editor is inside a scrollable container, you may need to configure the selection area's boundaries and scroll speed.
- Add an
id
to your scroll container, e.g.,id={editor.meta.uid}
. - Set
position: relative
on the container. - Use the
areaOptions
to configure the boundaries and scrolling behavior.
BlockSelectionPlugin.configure({
options: {
areaOptions: {
boundaries: `#${editor.meta.uid}`,
container: `#${editor.meta.uid}`,
behaviour: {
scrolling: {
// Recommended speed, close to native
speedDivider: 0.8,
},
// Threshold to start selection area
startThreshold: 4,
},
},
},
});
Full Page Selection
You can enable block selection for elements outside the <Editor />
component by adding the data-plate-selectable
attribute.
<Cover data-plate-selectable />
<Sidebar data-plate-selectable />
To prevent unselecting blocks when clicking on certain elements (e.g., a toolbar button), add the data-plate-prevent-unselect
attribute.
<YourToolbarButton data-plate-prevent-unselect />
To reset the selection when clicking outside selectable areas, you can use a click handler or call the API directly:
// 1. Direct API call
editor.api.blockSelection.deselect();
// 2. Click outside handler
const handleClickOutside = (event: MouseEvent) => {
if (!(event.target as HTMLElement).closest('[data-plate-selectable]')) {
editor.api.blockSelection.deselect();
}
};
Styling
Selection Area
Style the selection area by targeting the .slate-selection-area
class, which is added to the editor container.
/* Example using Tailwind CSS utility classes */
'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10'
Selected Element
Use the useBlockSelected
hook to determine if a block is selected. You can render a visual indicator, like the BlockSelection
component, which is designed for this purpose.
Plate UI renders this component for all selectable blocks using render.belowRootNodes
:
render: {
belowRootNodes: (props) => {
if (!props.className?.includes('slate-selectable')) return null;
return <BlockSelection />;
},
},
Plugins
BlockSelectionPlugin
Plugin for block selection functionality.
- Default:
false
- Default:
false
- Default:
{ maxLevel: 1 }
- Default:
new Set()
- Default:
null
- Default:
() => true
Options for the selection area. See SelectionJS docs for all available options.
{
boundaries: [`#${editor.meta.uid}`],
container: [`#${editor.meta.uid}`],
selectables: [`#${editor.meta.uid} .slate-selectable`],
selectionAreaClass: 'slate-selection-area',
}
Enables or disables the context menu for block selection.
Indicates whether block selection is currently active.
A function to handle the keydown event when selecting.
Options for querying nodes during block selection.
A set of IDs for the currently selected blocks.
(Internal) The ID of the anchor block in the current selection. Used for shift-based selection.
Function to determine if a block element is selectable.
API
api.blockSelection.add
Adds one or more blocks to the selection.
api.blockSelection.clear
Resets the set of selected IDs to an empty set.
api.blockSelection.delete
Removes one or more blocks from the selection.
api.blockSelection.deselect
Deselects all blocks and sets the isSelecting
flag to false.
api.blockSelection.focus
Focuses the block selection shadow input. This input handles copy, delete, and paste events for selected blocks.
api.blockSelection.getNodes
Gets the selected blocks in the editor.
api.blockSelection.has
Checks if one or more blocks are selected.
api.blockSelection.isSelectable
Checks if a block at a given path is selectable based on the isSelectable
plugin option.
api.blockSelection.moveSelection
Moves the selection up or down to the next selectable block.
When moving up:
- Gets the previous selectable block from the top-most selected block
- Sets it as the new anchor
- Clears previous selection and selects only this block When moving down:
- Gets the next selectable block from the bottom-most selected block
- Sets it as the new anchor
- Clears previous selection and selects only this block
api.blockSelection.selectAll
Selects all selectable blocks in the editor.
api.blockSelection.set
Sets the selection to one or more blocks, clearing any existing selection.
api.blockSelection.shiftSelection
Expands or shrinks the selection based on the anchor block.
For Shift+ArrowDown
:
- If anchor is top-most: Expands down by adding block below bottom-most
- Otherwise: Shrinks from top-most (unless top-most is the anchor)
For
Shift+ArrowUp
: - If anchor is bottom-most: Expands up by adding block above top-most
- Otherwise: Shrinks from bottom-most (unless bottom-most is the anchor) The anchor block always remains selected. If no anchor is set, it defaults to:
- Bottom-most block for
Shift+ArrowUp
- Top-most block for
Shift+ArrowDown
Transforms
tf.blockSelection.duplicate
Duplicates the selected blocks.
tf.blockSelection.removeNodes
Removes the selected nodes from the editor.
tf.blockSelection.select
Selects the nodes returned by getNodes()
in the editor and resets selected IDs.
tf.blockSelection.setNodes
Sets properties on the selected nodes.
tf.blockSelection.setTexts
Sets text properties on the selected nodes.
Hooks
useBlockSelectable
A hook that provides props for making a block element selectable, including context menu behavior.
useBlockSelected
useBlockSelectionNodes
useBlockSelectionFragment
useBlockSelectionFragmentProp
useSelectionArea
Initialize and manage selection area functionality.
On This Page
FeaturesKit UsageInstallationAdd KitManual UsageInstallationAdd PluginExcluding Blocks from SelectionCustomizing Scroll BehaviorFull Page SelectionStylingSelection AreaSelected ElementPluginsBlockSelectionPluginAPIapi.blockSelection.addapi.blockSelection.clearapi.blockSelection.deleteapi.blockSelection.deselectapi.blockSelection.focusapi.blockSelection.getNodesapi.blockSelection.hasapi.blockSelection.isSelectableapi.blockSelection.moveSelectionapi.blockSelection.selectAllapi.blockSelection.setapi.blockSelection.shiftSelectionTransformstf.blockSelection.duplicatetf.blockSelection.removeNodestf.blockSelection.selecttf.blockSelection.setNodestf.blockSelection.setTextsHooksuseBlockSelectableuseBlockSelecteduseBlockSelectionNodesuseBlockSelectionFragmentuseBlockSelectionFragmentPropuseSelectionArea