浮动菜单扩展
在 Tiptap 中使用浮动菜单扩展,使菜单在空行上出现。
如果您正在使用类似 React 或 Vue 的框架,请使用这些框架特定的 FloatingMenu 组件,而不是扩展。该组件提供了更便利的 API,并为您处理 DOM 元素。有关该组件的更多信息,请参见下方的框架中的使用部分。
安装扩展
安装浮动菜单扩展和 Floating UI 库。
npm install @tiptap/extension-floating-menu @floating-ui/dom@^1.6.0设置
element
包含您菜单的 DOM 元素。
类型: HTMLElement
默认值: null
updateDelay
FloatingMenu 对 update 方法进行防抖,以避免在每次选择更新时都更新浮动菜单。该延迟以毫秒为单位控制。
FloatingMenuPlugin 默认延迟为 250 毫秒。将延迟设置为 0 可以禁用防抖。
类型: Number
默认值: 250
resizeDelay
FloatingMenu 对 resize 和 scroll 事件处理程序进行防抖,以避免在每次大小调整或滚动时都更新浮动菜单。该延迟以毫秒为单位控制。
类型: Number
默认值: 60
appendTo
菜单应附加到 DOM 中的元素。可以是一个 HTMLElement,也可以是返回 HTMLElement 的回调函数。
类型: HTMLElement | (() => HTMLElement) | undefined
默认值: undefined,菜单将附加到 document.body。
options
在底层,FloatingMenu 使用 Floating UI。您可以使用这些选项控制浮动菜单的中间件和定位。
类型: Object
默认值: { strategy: 'absolute', placement: 'right' }
| 选项 | 类型 | 描述 |
|---|---|---|
strategy | string | 定位策略。请参见 这里 |
placement | string | 菜单的位置。请参见 这里 |
offset | OffsetOptions 或 boolean | 偏移中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件 |
flip | FlipOptions 或 boolean | 翻转中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件 |
shift | ShiftOptions 或 boolean | 移动中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件 |
arrow | ArrowOptions 或 false | 箭头中间件选项。如果为 false 禁用中间件 |
size | SizeOptions 或 boolean | 大小中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件 |
autoPlacement | AutoPlacementOptions 或 boolean | 自动放置中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件 |
hide | HideOptions 或 boolean | 隐藏中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件的 |
inline | InlineOptions 或 boolean | 内联中间件选项。如果为 true 使用默认选项,如果为 false 禁用中间件 |
onShow | Function 或 undefined | 菜单显示时调用的回调。可用于在菜单显示时添加自定义逻辑或样式。 |
onHide | Function 或 undefined | 菜单隐藏时调用的回调。可用于在菜单隐藏时添加自定义逻辑或样式。 |
onUpdate | Function 或 undefined | 菜单更新时调用的回调。可用于在菜单更新时添加自定义逻辑或样式。 |
onDestroy | Function 或 undefined | 菜单销毁时调用的回调。可用于在菜单被移除时添加自定义逻辑或样式。 |
pluginKey
底层 ProseMirror 插件的键。如果您添加多个实例,请确保使用不同的键。
类型: string | PluginKey
默认值: 'floatingMenu'
shouldShow
一个回调,用于控制菜单是否应显示。
类型: (props) => boolean
源代码
packages/extension-floating-menu/
在 Vanilla JavaScript 中使用
import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'
new Editor({
extensions: [
FloatingMenu.configure({
element: document.querySelector('.menu'),
}),
],
})框架中的使用
React
@tiptap/react 包提供了一个 FloatingMenu 组件,可以从 @tiptap/react/menus 导入。它提供了与扩展相同的功能,但使用了更适合 React 的 API。使用该组件时,无需将 FloatingMenu 扩展添加到编辑器中。
import { FloatingMenu } from '@tiptap/react/menus'
function MyFloatingMenu({ editor }) {
return (
<FloatingMenu editor={editor}>
<button onClick={() => editor.chain().focus().setHeading({ level: 1 }).run()}>
H1
</button>
<button onClick={() => editor.chain().focus().setBulletList().run()}>
List
</button>
</FloatingMenu>
)
}Vue
@tiptap/vue-3 包提供了一个 FloatingMenu 组件,可以从 @tiptap/vue-3/menus 导入。它提供了与扩展相同的功能,但使用了更适合 Vue 的 API。使用该组件时,无需将 FloatingMenu 扩展添加到编辑器中。
<template>
<FloatingMenu :editor="editor">
<button @click="editor.chain().focus().setHeading({ level: 1 }).run()">
H1
</button>
<button @click="editor.chain().focus().setBulletList().run()">
List
</button>
</FloatingMenu>
</template>
<script setup>
import { FloatingMenu } from '@tiptap/vue-3/menus'
// 确保将编辑器实例作为 prop 传递给 FloatingMenu 组件
const { editor } = defineProps({
editor: {
type: Object,
required: true,
},
})
</script>注意:相同的菜单也可在 Tiptap 的 Vue 2 版本中使用,可从 @tiptap/vue-2/menus 导入。
自定义逻辑
使用 shouldShow 选项自定义显示菜单的逻辑。对于组件,shouldShow 可以作为 prop 传递。
FloatingMenu.configure({
shouldShow: ({ editor, view, state, oldState }) => {
// 在任何段落中显示浮动菜单
return editor.isActive('paragraph')
},
})多个菜单
通过设置唯一的 pluginKey 使用多个菜单。
import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'
new Editor({
extensions: [
FloatingMenu.configure({
pluginKey: 'floatingMenuOne',
element: document.querySelector('.menu-one'),
}),
FloatingMenu.configure({
pluginKey: 'floatingMenuTwo',
element: document.querySelector('.menu-two'),
}),
],
})或者,您可以传递一个 ProseMirror PluginKey。
import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'
import { PluginKey } from '@tiptap/pm/state'
new Editor({
extensions: [
FloatingMenu.configure({
pluginKey: new PluginKey('floatingMenuOne'),
element: document.querySelector('.menu-one'),
}),
FloatingMenu.configure({
pluginKey: new PluginKey('floatingMenuTwo'),
element: document.querySelector('.menu-two'),
}),
],
})强制更新浮动菜单位置
If the floating menu changes size after the initial render, its position will not be adjusted automatically. To fix this, you can force update the position by setting a pluginKey on the extension and emitting an 'updatePosition' event with that key.
FloatingMenu.configure({
pluginKey: 'myFloatingMenu',
element: document.querySelector('.menu'),
})
editor.commands.setMeta('myFloatingMenu', 'updatePosition')To target a specific floating menu, emit an 'updatePosition' event via transaction metadata and use that menu's pluginKey:
FloatingMenu.configure({
pluginKey: 'myFloatingMenu',
element: document.querySelector('.menu'),
})For example, if you have multiple floating menus:
editor.commands.setMeta('floatingMenuOne', 'updatePosition')If you use the React or Vue FloatingMenu component and want to trigger updatePosition externally, pass an explicit pluginKey prop to the component first. If you omit pluginKey, the component creates its own ProseMirror PluginKey, which external code cannot reliably reference later.
Programmatically show or hide the floating menu
You can programmatically show or hide the floating menu by setting a pluginKey on the extension and dispatching a transaction with the 'show' or 'hide' meta value using that key.
// Show the floating menu
editor.commands.setMeta('myFloatingMenu', 'show')
// Hide the floating menu
editor.commands.setMeta('myFloatingMenu', 'hide')Note: dispatching 'show' or 'hide' will override the behavior defined in shouldShow.