BubbleMenu 扩展

版本下载次数

此扩展会在文本选择附近显示上下文菜单。用户可以对其文本选择应用 标记

和往常一样,标记和样式完全由您决定。

如果您使用的是 React 或 Vue 等框架,请使用特定于框架的 BubbleMenu 组件,而不是扩展。该组件提供了更方便的 API,并为您处理 DOM 元素。您可以在下方的与框架一起使用章节中找到有关该组件的更多信息。

安装

npm install @tiptap/extension-bubble-menu

设置

element

包含您的菜单的 DOM 元素。

类型: HTMLElement

默认: null

在 React 版本的 BubbleMenu 中,可通过 BubbleMenu 组件的 ref 属性访问 DOM 元素,方法是将 ref 传递 给它。

updateDelay

BubbleMenu 会对 update 方法进行去抖动,以允许气泡菜单不会在每次选择更新时进行更新。此延迟可以以毫秒为单位进行控制。

BubbleMenuPlugin 默认有 250 毫秒的延迟。将延迟设置为 0 可禁用该功能,从而禁用去抖动。

类型: Number

默认: undefined

resizeDelay

BubbleMenu 会对气泡菜单大小的计算进行去抖动,以允许气泡菜单不会在每次调整大小事件时更新。此延迟可以以毫秒为单位进行控制。

类型: Number

默认: 100

options

在底层,BubbleMenu 使用 Floating UI。您可以使用这些选项控制浮动菜单的中间件和定位。

类型: Object

默认: { strategy: 'absolute', placement: 'right' }

选项类型描述
strategystring定位策略。请参见 这里
placementstring菜单的位置。请参见 这里
offsetnumber, OffsetOptionsboolean偏移中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
flipFlipOptionsboolean翻转中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
shiftShiftOptionsboolean移动中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
arrowArrowOptionsfalse箭头中间件选项。如果为 false,则禁用中间件
sizeSizeOptionsboolean大小中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
autoPlacementAutoPlacementOptionsboolean自动定位中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
hideHideOptionsboolean隐藏中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
inlineInlineOptionsboolean内联中间件选项。如果为 true,则使用默认选项;如果为 false,则禁用中间件
onShowFunctionundefined菜单显示时调用的回调函数。可用于在菜单显示时添加自定义逻辑或样式。
onHideFunctionundefined菜单隐藏时调用的回调函数。可用于在菜单隐藏时添加自定义逻辑或样式。
onUpdateFunctionundefined菜单更新时调用的回调函数。可用于在菜单更新时添加自定义逻辑或样式。
onDestroyFunctionundefined菜单销毁时调用的回调函数。可用于在菜单移除时添加自定义逻辑或样式。

pluginKey

底层 ProseMirror 插件的键。如果添加多个实例,请确保使用不同的键。

类型: string | PluginKey

默认: 'bubbleMenu'

shouldShow

一个回调,用于控制菜单是否应该显示。

类型: (props) => boolean

appendTo

气泡菜单应该被附加到 DOM 中的元素。可以是 HTMLElement,也可以是返回 HTMLElement 的回调函数。

类型: HTMLElement | (() => HTMLElement) | undefined

默认: undefined,菜单将附加到编辑器的父元素(editor.view.dom.parentElement)。

getReferencedVirtualElement

一个回调,用于提供用于定位菜单的锚点坐标。应返回 Floating UI 预期的 虚拟元素

类型: () => VirtualElement | null

默认: null,锚点由编辑器选区隐式确定。

源代码

packages/extension-bubble-menu/

使用扩展

JavaScript

import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'

new Editor({
  extensions: [
    BubbleMenu.configure({
      element: document.querySelector('.menu'),
    }),
  ],
})

与框架一起使用

React

@tiptap/react 包含一个可从 @tiptap/react/menus 导入的 BubbleMenu 组件。它提供与扩展相同的功能,但采用了更适合 React 的 API。使用此组件时,无需将 BubbleMenu 扩展添加到编辑器中。

import { BubbleMenu } from '@tiptap/react/menus'

function MyBubbleMenu({ editor }) {
  return (
    <BubbleMenu editor={editor}>
      <button onClick={() => editor.chain().focus().toggleBold().run()}>
        Bold
      </button>
      <button onClick={() => editor.chain().focus().toggleItalic().run()}>
        Italic
      </button>
    </BubbleMenu>
  )
}

Vue

@tiptap/vue-3 包含一个可从 @tiptap/vue-3/menus 导入的 BubbleMenu 组件。它提供与扩展相同的功能,但采用了更适合 Vue 的 API。使用此组件时,无需将 BubbleMenu 扩展添加到编辑器中。

<template>
  <BubbleMenu :editor="editor">
    <button @click="editor.chain().focus().toggleBold().run()">
      Bold
    </button>
    <button @click="editor.chain().focus().toggleItalic().run()">
      Italic
    </button>
  </BubbleMenu>
</template>

<script setup>
  import { BubbleMenu } from '@tiptap/vue-3/menus'
  
  // 确保将编辑器实例作为属性传递给 BubbleMenu 组件
  const { editor } = defineProps({
    editor: {
      type: Object,
      required: true,
    },
  })
</script>

注意:相同的菜单也可用于 Vue 2 版本的 Tiptap,您可以从 @tiptap/vue-2/menus 导入。

自定义逻辑

使用 shouldShow 选项自定义显示菜单的逻辑。对于组件,shouldShow 可以作为道具传递。

BubbleMenu.configure({
  shouldShow: ({ editor, view, state, oldState, from, to }) => {
    // 仅对图像和链接显示气泡菜单
    return editor.isActive('image') || editor.isActive('link')
  },
})

多个菜单

通过设置唯一的 pluginKey 使用多个菜单。

import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'

new Editor({
  extensions: [
    BubbleMenu.configure({
      pluginKey: 'bubbleMenuOne',
      element: document.querySelector('.menu-one'),
    }),
    BubbleMenu.configure({
      pluginKey: 'bubbleMenuTwo',
      element: document.querySelector('.menu-two'),
    }),
  ],
})

或者,您可以传递一个 ProseMirror PluginKey

import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'
import { PluginKey } from '@tiptap/pm/state'

new Editor({
  extensions: [
    BubbleMenu.configure({
      pluginKey: new PluginKey('bubbleMenuOne'),
      element: document.querySelector('.menu-one'),
    }),
    BubbleMenu.configure({
      pluginKey: new PluginKey('bubbleMenuTwo'),
      element: document.querySelector('.menu-two'),
    }),
  ],
})

强制更新气泡菜单位置

If the bubble 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.

BubbleMenu.configure({
  pluginKey: 'myBubbleMenu',
  element: document.querySelector('.menu'),
})

editor.commands.setMeta('myBubbleMenu', 'updatePosition')

To target a specific bubble menu, pass that menu's pluginKey instead.

editor.commands.setMeta('bubbleMenuOne', 'updatePosition')

If you use the React or Vue BubbleMenu 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 bubble menu

You can programmatically show or hide the bubble menu by setting a pluginKey on the extension and dispatching a transaction with the 'show' or 'hide' meta value using that key.

BubbleMenu.configure({
  pluginKey: 'myBubbleMenu',
  element: document.querySelector('.menu'),
})

// Show the bubble menu
editor.commands.setMeta('myBubbleMenu', 'show')

// Hide the bubble menu
editor.commands.setMeta('myBubbleMenu', 'hide')

Note: dispatching 'show' or 'hide' will override the behavior defined in shouldShow.