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>
  );
}
Dynamic TOC with in-document element for easy navigation.
toc-demo
toc-demo

功能特性

  • 自动从文档标题生成目录
  • 平滑滚动至标题位置

套件使用

安装

最快捷的目录功能添加方式是使用 TocKit,它已预配置了 Plate UI 组件的 TocPlugin

'use client';

import { TocPlugin } from '@platejs/toc/react';

import { TocElement } from '@/components/ui/toc-node';

export const TocKit = [
  TocPlugin.configure({
    options: {
      // isScroll: true,
      topOffset: 80,
    },
  }).withComponent(TocElement),
];

添加套件

将套件加入插件列表:

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

手动配置

安装

pnpm add @platejs/basic-nodes @platejs/toc

添加插件

在创建编辑器时,将 TocPluginHnPlugin 加入 Plate 插件数组。

import { TocPlugin } from '@platejs/toc/react';
import { H1Plugin, H2Plugin, H3Plugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
 
const editor = createPlateEditor({
  plugins: [
    // ...其他插件
    H1Plugin,
    H2Plugin,
    H3Plugin,
    TocPlugin,
  ],
});

配置插件

使用自定义组件和滚动选项配置 TocPlugin

import { TocPlugin } from '@platejs/toc/react';
import { H1Plugin, H2Plugin, H3Plugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
import { TocElement } from '@/components/ui/toc-node';
import { H1Element, H2Element, H3Element } from '@/components/ui/heading-node';
 
const editor = createPlateEditor({
  plugins: [
    // ...其他插件
    H1Plugin.withComponent(H1Element),
    H2Plugin.withComponent(H2Element),
    H3Plugin.withComponent(H3Element),
    TocPlugin.configure({
      node: { component: TocElement },
      options: {
        topOffset: 80,
        isScroll: true,
      },
    }),
  ],
});
  • node.component: 指定渲染目录元素的 TocElement
  • options.topOffset: 设置滚动至标题时的顶部偏移量
  • options.isScroll: 启用滚动至标题的行为

添加工具栏按钮

可将此项加入插入工具栏按钮来插入目录元素:

{
  icon: <TableOfContentsIcon />,
  label: '目录',
  value: KEYS.toc,
}

滚动容器设置

  • 若您的滚动元素是 EditorContainer,可跳过此步骤
  • 若您的滚动元素是编辑器容器,将 useEditorContainerRef() 作为 ref 属性传入。例如:
// 在 <Plate> 组件下方
function EditorContainer({ children }: { children: React.ReactNode }) {
  const containerRef = useEditorContainerRef();
 
  return <div ref={containerRef}>{children}</div>;
}
  • 若您的滚动元素是编辑器容器的祖先元素,将 useEditorScrollRef() 作为 ref 属性传入。例如:
// 在 <Plate> 组件下方
function Layout() {
  const scrollRef = useEditorScrollRef();
 
  return (
    <main ref={scrollRef}>
      <EditorContainer>
        <PlateContent />
      </EditorContainer>
    </main>
  );
}

Plate Plus

toc
toc

插件

TocPlugin

目录生成插件。

Options

Collapse all

    启用滚动行为

    • 默认值: true

    滚动至标题时的顶部偏移量

    • 默认值: 80

    自定义标题查询函数

转换器

tf.insertToc

插入目录元素。

OptionsInsertNodesOptions<SlateEditor>

Collapse all

    节点插入选项

钩子

useTocElementState

管理 TOC 元素状态。

Returns

Collapse all

    文档标题数组

    标题滚动处理器

useTocElement

处理 TOC 元素交互。

Parameters

Collapse all

    来自 useTocElementState 的滚动处理器

Returns

Collapse all

    TOC 元素属性

useTocSideBarState

管理 TOC 侧边栏状态。

Parameters

Collapse all

    初始展开状态

    • 默认值: true

    Intersection Observer 根边距

    • 默认值: '0px 0px 0px 0px'

    滚动顶部偏移量

    • 默认值: 0

Returns

Collapse all

    当前活动区块 ID

    文档标题列表

    鼠标悬停 TOC 状态

    侧边栏展开状态

    设置观察状态

    设置鼠标悬停状态

    TOC 元素引用

    内容滚动处理器

useTocSideBar

该钩子为 TOC 侧边栏组件提供属性和处理器。

Parameters

Collapse all

    鼠标悬停 TOC 状态

    侧边栏展开状态

    设置观察状态

    设置鼠标悬停状态

    TOC 元素引用

    内容滚动处理器

Returns

Collapse all

    导航元素属性

    navProps.onContentClick (e: React.MouseEvent<HTMLElement, MouseEvent>, item: Heading, behavior?: ScrollBehavior) => void

    TOC 项点击处理器