拖拽功能

通过拖拽区块来重新组织编辑器中的内容。

Files
components/demo.tsx
'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>
  );
}
Implements draggable functionality for editor blocks, including drag handles and drop indicators.
dnd-demo
dnd-demo

功能特性

  • 通过拖拽区块实现内容移动和插入
  • 拖拽至视窗边缘时自动滚动
  • 支持文件拖放插入媒体区块
  • 可视化拖放指示器和拖拽手柄

套件使用

安装

最快捷的方式是使用 DndKit 套件,它包含预配置的 DndPlugin、React DnD 设置以及 BlockDraggable UI组件。

'use client';

import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

import { DndPlugin } from '@platejs/dnd';
import { PlaceholderPlugin } from '@platejs/media/react';

import { BlockDraggable } from '@/components/ui/block-draggable';

export const DndKit = [
  DndPlugin.configure({
    options: {
      enableScroller: true,
      onDropFiles: ({ dragItem, editor, target }) => {
        editor
          .getTransforms(PlaceholderPlugin)
          .insert.media(dragItem.files, { at: target, nextBlock: false });
      },
    },
    render: {
      aboveNodes: BlockDraggable,
      aboveSlate: ({ children }) => (
        <DndProvider backend={HTML5Backend}>{children}</DndProvider>
      ),
    },
  }),
];

添加套件

import { createPlateEditor } from 'platejs/react';
import { DndKit } from '@/components/editor/plugins/dnd-kit';
 
const editor = createPlateEditor({
  plugins: [
    // ...其他插件
    ...DndKit,
  ],
});

手动配置

安装依赖

pnpm add @platejs/dnd react-dnd react-dnd-html5-backend

添加插件

import { DndPlugin } from '@platejs/dnd';
import { createPlateEditor } from 'platejs/react';
 
const editor = createPlateEditor({
  plugins: [
    // ...其他插件
    DndPlugin,
  ],
});

配置插件

通过可拖拽组件和DnD provider配置拖放功能:

import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { DndPlugin } from '@platejs/dnd';
 
DndPlugin.configure({
  render: {
    aboveSlate: ({ children }) => (
      <DndProvider backend={HTML5Backend}>{children}</DndProvider>
    ),
  },
});
  • render.aboveNodes: 分配 BlockDraggable 组件在区块上方渲染拖拽手柄
  • render.aboveSlate: 用 DndProvider 包裹编辑器。如果React树中已有 DndProvider 可移除此配置

高级配置

添加自动滚动和文件拖放处理:

import { DndPlugin } from '@platejs/dnd';
import { PlaceholderPlugin } from '@platejs/media/react';
 
DndPlugin.configure({
  options: {
    enableScroller: true,
    onDropFiles: ({ dragItem, editor, target }) => {
      editor
        .getTransforms(PlaceholderPlugin)
        .insert.media(dragItem.files, { at: target, nextBlock: false });
    },
  },
  render: {
    aboveNodes: BlockDraggable,
    aboveSlate: ({ children }) => (
      <DndProvider backend={HTML5Backend}>{children}</DndProvider>
    ),
  },
});
  • enableScroller: 启用拖拽至视窗边缘时的自动滚动
  • onDropFiles: 处理文件拖放,在目标位置插入媒体区块

插件

DndPlugin

实现编辑器内拖拽功能的插件。

Options

Collapse all

    是否启用拖拽至视窗边缘自动滚动

    • 默认值: false

    当启用滚动时的 Scroller 组件属性

    文件拖放事件处理器

    当前拖放目标状态,包含目标元素ID和放置线方向

API

focusBlockStartById

通过ID选中区块起始位置并聚焦编辑器。

Parameters

Collapse all

    要聚焦的区块ID

getBlocksWithId

返回带有ID的区块数组。

OptionsEditorNodesOptions

Collapse all

    获取节点条目的选项

ReturnsNodeEntry[]

Collapse all

    带有ID的区块数组

selectBlockById

通过ID选中区块。

Parameters

Collapse all

    要选中的区块ID

钩子

useDndNode

组合了 useDragNodeuseDropNode 的自定义钩子,用于启用编辑器节点的拖拽功能。提供默认的拖拽预览效果,可自定义或禁用。

OptionsUseDndNodeOptions

Collapse all

    要拖拽的节点

    拖拽项类型

    • 默认值: 'block'

    节点拖拽引用

    拖拽方向

    • 默认值: 'vertical'

    判断节点能否放置到当前位置的回调

    拖拽节点的预览选项

    拖拽节点的拖拽选项

    拖拽节点的放置选项

    节点放置时的处理函数

Returnsobject

Collapse all

    节点是否正在被拖拽

    拖拽节点是否在放置目标上方

    可拖拽元素的拖拽引用

useDragNode

使用 react-dnduseDrag 钩子实现节点拖拽功能的自定义钩子。

OptionsUseDragNodeOptions

Collapse all

    要拖拽的节点

    拖拽对象或其工厂函数

useDraggable

使元素具备可拖拽行为的自定义钩子,提供可自定义或禁用的拖拽预览效果。

Optionsobject

Collapse all

    要设为可拖拽的元素

    拖拽方向

    • 默认值: 'vertical'

    拖拽项类型

    • 默认值: 'block'

    元素放置时的处理函数

Returnsobject

Collapse all

    拖拽源连接函数

    元素是否正在被拖拽

    可拖拽元素的引用

useDropNode

使用 react-dnduseDrop 钩子实现节点放置功能的自定义钩子。

OptionsUseDropNodeOptions

Collapse all

    被拖拽节点的引用

    放置线依附的节点

    当前放置线的值

    放置线变化时的回调

    拦截放置处理的回调

    • 返回 true 阻止默认行为
    • 返回 false 执行默认行为

useDropLine

返回元素的当前放置线状态。

Optionsobject

Collapse all

    显示放置线的元素ID

    • 默认值: 当前元素ID

    按方向过滤放置线

    • 默认值: 'vertical'

Returnsobject

Collapse all

    当前放置线方向