自定义内联内容类型
除了 BlockNote 提供的默认内联内容类型外,您还可以使用 React 组件创建自己的自定义内联内容。请看下面的示例演示,我们在 BlockNote 编辑器中添加了一个自定义提及标签,以及一个自定义的 建议菜单 用于插入它。
创建自定义内联内容类型
使用 createReactInlineContentSpec 函数来创建自定义内联内容类型。该函数接受两个参数:
function createReactInlineContentSpec(
blockConfig: CustomInlineContentConfig,
blockImplementation: ReactInlineContentImplementation,
): InlineContentSpec;它返回您的自定义内联内容的实例,或者一个 InlineContentSpec。此 InlineContentSpec 会传递到您的 BlockNote schema 中,以将内联内容添加到编辑器。
让我们看看演示中的自定义提及标签,并逐个字段解释其作用:
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。
在提及标签示例中,我们希望每个提及都是一个不可编辑的单一元素,因此将 content 设置为 "none"。
propSchema: PropSchema 指定内联内容支持的属性。内联内容的 props 是随文档中内联内容一起存储的数据,可用于自定义其外观或行为。
type PropSchema<PrimitiveType extends "boolean" | "number" | "string"> = Record<
string,
| {
default: PrimitiveType;
values?: PrimitiveType[];
}
| {
default: undefined;
type: PrimitiveType;
values?: PrimitiveType[];
}
>;[key: string] 是属性的名称。如果希望该属性有默认值,则应定义为具有以下属性的对象:
-
default:指定属性的默认值,由此推断PrimitiveType。 -
values?:指定该属性可取的值的数组,例如,用于限制值为预定义字符串列表。如果未定义values,BlockNote 默认属性可以是任何PrimitiveType类型的值。
如果不希望该属性有默认值,可以定义为具有以下属性的对象:
-
default:设为undefined,表示无默认值。 -
type:指定该属性可以设置的PrimitiveType,因为默认值为undefined,无法推断类型。 -
values?:指定该属性可取的值的数组,例如限制为预定义字符串列表。如果未定义values,BlockNote 默认属性可以是任何PrimitiveType类型的值。
在提及标签示例中,我们为被提及的用户添加了一个 user 属性。
draggable?: 指定该内联内容是否可以被拖拽。
内联内容实现 (ReactCustomInlineContentImplementation)
内联内容实现定义了内联内容如何渲染为 HTML。
type ReactCustomInlineContentImplementation = {
meta?: {
draggable?: boolean;
};
render: React.FC<{
inlineContent: InlineContent;
editor: BlockNoteEditor;
contentRef?: (node: HTMLElement | null) => void;
}>;
toExternalHTML?: React.FC<{
inlineContent: InlineContent;
editor: BlockNoteEditor;
contentRef?: (node: HTMLElement | null) => void;
}>;
parse?: (element: HTMLElement) => PartialInlineContent["props"] | undefined;
};render: 这是您的 React 组件,定义了如何渲染自定义内联内容,并接收三个 React props:
-
inlineContent:应渲染的内联内容。其类型和属性将匹配内联内容配置中定义的类型和PropSchema。 -
contentRef:一个 Reactref,可用于标记内联内容中可编辑的元素,仅当内联内容配置包含content: "styled"时可用。 -
draggable:指定内联内容是否可以在编辑器内拖动。设置为true时,内联内容将可拖动。若未指定,默认为false。若为true,应在用作拖动句柄的 DOM 元素上添加data-drag-handle属性。
toExternalHTML?: 该组件用于将内联内容导出为外部 HTML(例如复制到剪贴板时)。如果未定义,BlockNote 将使用 render 进行 HTML 转换。接收与 render 相同的 props。
注意,传递给 toExternalHTML 的组件会在单独的 React 根中渲染和序列化,这意味着您不能使用依赖 React Context 的 hooks。
parse?: parse 函数定义如何将 HTML 内容解析为您的内联内容,例如从剪贴板粘贴内容时。如果元素应被解析为您的自定义内联内容,则返回该内联内容应具有的 props,否则返回 undefined。接收一个参数:
element:正在解析的 HTML 元素。
meta?.draggable?: 指定内联内容是否可拖动。
注意,由于内联内容本质上是内联的,您的组件应返回一个 HTML 内联元素。
向编辑器添加自定义内联内容
最后,使用您自定义内联内容的定义创建一个 BlockNoteSchema:
const schema = BlockNoteSchema.create({
inlineContentSpecs: {
// 如需要,可启用默认内联内容
...defaultInlineContentSpecs,
// 添加您自己的自定义内联内容:
mention: Mention,
},
});然后您可以使用此自定义 schema 实例化您的编辑器,具体方法请参见 自定义 Schema 页面。