文档
Custom Inline Content

自定义内联内容类型

除了 BlockNote 提供的默认内联内容类型外,你还可以使用 React 组件创建自己的自定义内联内容。请看下面的演示,我们在 BlockNote 编辑器中添加了一个自定义的提及标签(mention tag),以及一个用于插入该标签的自定义建议菜单

import {
  BlockNoteSchema,
  defaultInlineContentSpecs,
  filterSuggestionItems,
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import {
  DefaultReactSuggestionItem,
  SuggestionMenuController,
  useCreateBlockNote,
} from "@blocknote/react";
 
import { Mention } from "./Mention.js";
 
// Our schema with inline content specs, which contain the configs and
// implementations for inline content  that we want our editor to use.
const schema = BlockNoteSchema.create({
  inlineContentSpecs: {
    // Adds all default inline content.
    ...defaultInlineContentSpecs,
    // Adds the mention tag.
    mention: Mention,
  },
});
 
// Function which gets all users for the mentions menu.
const getMentionMenuItems = (
  editor: typeof schema.BlockNoteEditor,
): DefaultReactSuggestionItem[] => {
  const users = ["Steve", "Bob", "Joe", "Mike"];
 
  return users.map((user) => ({
    title: user,
    onItemClick: () => {
      editor.insertInlineContent([
        {
          type: "mention",
          props: {
            user,
          },
        },
        " ", // add a space after the mention
      ]);
    },
  }));
};
 
export function App() {
  const editor = useCreateBlockNote({
    schema,
    initialContent: [
      {
        type: "paragraph",
        content: "Welcome to this demo!",
      },
      {
        type: "paragraph",
        content: [
          {
            type: "mention",
            props: {
              user: "Steve",
            },
          },
          {
            type: "text",
            text: " <- This is an example mention",
            styles: {},
          },
        ],
      },
      {
        type: "paragraph",
        content: "Press the '@' key to open the mentions menu and add another",
      },
      {
        type: "paragraph",
      },
    ],
  });
 
  return (
    <BlockNoteView editor={editor}>
      {/* Adds a mentions menu which opens with the "@" key */}
      <SuggestionMenuController
        triggerCharacter={"@"}
        getItems={async (query) =>
          // Gets the mentions menu items
          filterSuggestionItems(getMentionMenuItems(editor), query)
        }
      />
    </BlockNoteView>
  );
}
 
export default App;
 

创建自定义内联内容类型

使用 createReactInlineContentSpec 函数来创建自定义内联内容类型。该函数接受两个参数:

function createReactInlineContentSpec(
  blockConfig: CustomInlineContentConfig,
  blockImplementation: ReactInlineContentImplementation,
);

让我们看看演示中的自定义提及标签,并逐个字段解释其作用:

const Mention = createReactInlineContentSpec(
  {
    type: "mention",
    propSchema: {
      user: {
        default: "Unknown",
      },
    },
    content: "none",
  } as const,
  {
    render: (props) => (
      ...
    ),
  }
);

内联内容配置 (CustomInlineContentConfig)

内联内容配置描述你的自定义内联内容的结构。用它来指定自定义内联内容应该支持的类型、属性(props)和内容:

type CustomInlineContentConfig = {
  type: string;
  content: "styled" | "none";
  readonly propSchema: PropSchema;
};

type

定义自定义内联内容的标识符。

content

如果你的自定义内联内容应包含 StyledText,则设置为 styled,否则为 none

在提及示例中,我们希望每个提及是一个单独的、不可编辑的元素,所以设置为 "none"

propSchema

PropSchema 指定内联内容支持的 props。内联内容的 props(属性)是在文档中随内联内容存储的数据,可以用来定制其外观或行为。

type PropSchema<
  PrimitiveType extends "boolean" | "number" | "string"
> = Record<
  string,
  {
    default: PrimitiveType;
    values?: PrimitiveType[];
  }
>

[key: string] 是 prop 的名称,值是包含两个字段的对象:

  • default:指定该 prop 的默认值

  • values(可选):指定该 prop 可以取的值的数组,例如限制该值为预定义字符串列表。如果未定义 values,BlockNote 认为该 prop 可以是任何 PrimitiveType 的值

在提及演示中,我们添加了一个 user prop,用于指定被提及的用户。

内联内容实现 (ReactCustomInlineContentImplementation)

内联内容实现定义了内联内容如何渲染为 HTML。

type ReactCustomInlineContentImplementation = {
  render: React.FC<{
    inlineContent: InlineContent;
    contentRef?: (node: HTMLElement | null) => void;
  }>;
};

render

这是你的 React 组件,用于定义自定义内联内容的渲染方式,接受两个 React props:

inlineContent: 需要渲染的内联内容。其类型和 props 会匹配内联内容配置中定义的类型和 PropSchema

contentRef: React ref,用于标记内联内容中可编辑的元素,仅当你的内联内容配置中包含 content: "styled" 时提供。

注意,由于内联内容本质上是内联的,你的组件也应返回一个 HTML 内联元素。

向编辑器添加自定义内联内容

最后,使用你自定义内联内容的定义创建一个 BlockNoteSchema:

const schema = BlockNoteSchema.create({
  inlineContentSpecs: {
    // 如果需要,可以启用默认内联内容
    ...defaultInlineContentSpecs,
 
    // 添加你自己的自定义内联内容:
    mention: Mention,
  },
});

然后如自定义 Schema 页面所述,用该自定义 schema 实例化编辑器即可。