Block Selection

Loading...
Files
components/demo.tsx
'use client';

import React from 'react';

import { Plate } from '@udecode/plate/react';

import { editorPlugins } from '@/components/editor/plugins/editor-plugins';
import { useCreateEditor } from '@/components/editor/use-create-editor';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';

import { DEMO_VALUES } from './values/demo-values';

export default function Demo({ id }: { id: string }) {
  const editor = useCreateEditor({
    plugins: [...editorPlugins],
    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. This powerful functionality enhances the editing experience by providing efficient ways to manage large sections of content.

Features

  • Select entire blocks with a single action
  • Multi-block selection
  • Copy, cut, and delete operations on selected blocks
  • Keyboard shortcuts for quick selection:
    • Cmd+A:
      • First press: select the current block
      • Double press: select all blocks
    • Arrow keys: select the block above or below
  • Customizable styling for selected blocks

Installation

npm install @udecode/plate-selection @udecode/plate-node-id

Usage

import { NodeIdPlugin } from '@udecode/plate-node-id';
import { BlockSelectionPlugin } from '@udecode/plate-selection/react';
 
const plugins = [
  // ...otherPlugins,
  NodeIdPlugin,
  BlockSelectionPlugin,
];

Exclude blocks from selection

You can exclude certain plugins from block selection using:

BlockSelectionPlugin.configure({
  inject: {
    // Exclude blocks below table rows
    excludeBelowPlugins: ['tr'],
    // Exclude block types
    excludePlugins: ['table', 'code_line', 'column_group', 'column'],
  }
})
  • excludeBelowPlugins: Plugin keys of non-selectable block descendants. Use this to prevent selection below specific blocks. For example, excluding 'tr' prevents selecting individual cells while still allowing table row selection.

  • excludePlugins: Plugin keys of non-selectable blocks.

Set scrollable container

If you're using EditorContainer from Editor, you can skip this section.

To control the scrollable container, configure the boundaries and container options within areaOptions. These options accept CSS selectors, such as #selection-demo #${editor.uid}, which are used with document.querySelector().

For this to work effectively:

  1. Add an id or className to your scroll container. If you're not sure about the container, you can add it to the <Editor /> component. We recommend using id={editor.uid}.
  2. Use the appropriate selector in your configuration.
  3. Don't forget to set position: relative to the container.

Default configuration:

BlockSelectionPlugin.configure({
  options: {
    areaOptions: {
      boundaries: `#${editor.uid}`,
      container: `#${editor.uid}`,
      selectables: `#${editor.uid} .slate-selectable`,
    },
  },
});

Set scroll speed

Use options.areaOptions.behaviour.scrolling.speedDivider to set the scroll speed.

The value 0.8 is our recommended speed since it's near the browser-native speed.

BlockSelectionPlugin.configure({
  options: {
    areaOptions: {
      behaviour: {
        scrolling: {
          // You can slow down the scroll speed by setting a bigger value.
          speedDivider: 1.5,
        },
        // The distance needed to move for the selection area to appear.
        // If it's too small, it may cause the mouse click event to be blocked. 10 is a good default.
        startThreshold: 4,
      },
    },
  },
});

Add selectable element

Add data-plate-selectable="true" to any element you want to start block selection.

Prevent unselect

To prevent unselecting blocks when clicking on certain elements, add the data-plate-prevent-unselect attribute to those components

For example:

<YourSpecialButtoon data-plate-prevent-unselect />

Full Page Selection

Making Elements Selectable

You can enable block selection for elements outside the <Editor /> component, similar to the Potion template. Add the data-plate-selectable attribute to any component you want to make selectable:

<Cover data-plate-selectable />
<Sidebar data-plate-selectable />

This works for any element, even those outside the editor's DOM tree.

Resetting Selection

There are two ways to handle resetting selection across the full page:

  1. Direct API call:
editor.api.blockSelection.unselect();
  1. Click outside handler:
const handleClickOutside = (event: MouseEvent) => {
  if (!(event.target as HTMLElement).closest('[data-plate-selectable]')) {
    editor.api.blockSelection.unselect();
  }
};

Styling

Selection area

Style the selection area by adding the .slate-selection-area class to your editor container component. For example:

'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10'

Selected element

To determine if an element is selected, use useBlockSelected hook. You can render a visual indicator around selected blocks using our BlockSelection component or create your own.

This component should be rendered inside each block element for consistent selection feedback. Plate UI is doing it in PlateElement.

Plugins

BlockSelectionPlugin

Options

Collapse all

    Options for the selection area.

    Editor padding right.

    Plugin keys of non-selectable block descendants.

    Plugin keys of non-selectable blocks.

API

editor.api.blockSelection.add

Parameters

Collapse all

    The ID of the block to add to selection.

    Options for adding the block.

Optionsobject

Collapse all

    Whether to clear existing selections before adding the new one.

    • Default: true

editor.api.blockSelection.getNodes

ReturnsNodeEntry[]

    Array of selected block entries.

editor.api.blockSelection.resetSelectedIds

Reset the set of selected IDs to an empty set.

editor.api.blockSelection.selectedAll

Select all selectable blocks in the editor.

editor.api.blockSelection.setSelectedIds

Parameters

Collapse all

    Elements to add/remove from selection.

OptionsChangedElements

Collapse all

    Elements to add to selection.

    Elements to remove from selection.

editor.api.blockSelection.unselect

Unselect all blocks and set isSelecting to false.

Transforms

editor.tf.blockSelection.duplicate

Duplicate the selected blocks.

editor.tf.blockSelection.removeNodes

Remove the selected nodes from the editor.

editor.tf.blockSelection.select

Select the nodes returned by getNodes() and reset selected IDs.

editor.tf.blockSelection.setNodes

Parameters

Collapse all

    Properties to set on selected nodes.

    Options for setting nodes.

editor.tf.blockSelection.setTexts

Parameters

Collapse all

    Text properties to set on selected nodes.

    Options for setting text nodes.

Hooks

useBlockSelectable

Returns{ props: object }

Collapse all

    Props for the block element:

    • className: 'slate-selectable'
    • onContextMenu: Handler for right-click menu

useBlockSelected

Returnsboolean

    Whether the context block is selected.

useBlockSelectionNodes

ReturnsNodeEntry[]

    Array of selected block entries.

useBlockSelectionFragment

ReturnsNode[]

    Array of selected block nodes.

useBlockSelectionFragmentProp

ReturnsNode[]

    Fragment prop for selected blocks.

useSelectionArea

Initialize and manage selection area functionality.

editor.api.blockSelection.isSelectable

Parameters

Collapse all

    Block element to check.

    Path to the block element.

Returnsboolean

    Whether the block is selectable.

editor.api.blockSelection.moveSelection

Parameters

Collapse all

    Direction to move selection.

editor.api.blockSelection.shiftSelection

Parameters

Collapse all

    Direction to expand/shrink selection.