---
title: "编号格式下拉菜单"
description: "为你的 Tiptap 编辑器添加一个用于有序列表编号样式（十进制、字母、罗马数字、嵌套）的选择器。更多内容请查看文档！"
canonical_url: "https://tiptap.zhcndoc.com/ui-components/components/numbering-format-dropdown-menu"
---

# 编号格式下拉菜单

为你的 Tiptap 编辑器添加一个用于有序列表编号样式（十进制、字母、罗马数字、嵌套）的选择器。更多内容请查看文档！

一个用于有序列表的编号样式选择器。它会渲染一个 `ListButton` 来切换有序列表，并附带一个编号样式下拉菜单——包括十进制、括号样式、嵌套十进制、大小写字母、大小写罗马数字以及前导零格式——每种样式都以一个小型嵌套列表预览的形式显示。

当前激活的格式通过 **`orderedListNumbering` 扩展**（属于 `@tiptap-pro/extension-convert-kit`）读取并应用，因此屏幕上的标记始终与已注册的格式保持一致。所有编辑器逻辑都通过 `useNumberingFormatDropdownMenu` 钩子暴露，因此你可以在其基础上构建完全自定义的 UI。

> **Interactive demo:** [numbering format dropdown menu](https://template.tiptap.dev/preview/tiptap-ui/numbering-format-dropdown-menu)

> **Requires the orderedListNumbering extension:**
>
> 这个组件会在最外层有序列表上读取并写入一个 `numberingFormat` id。对应的
> 级别定义（即每个 id 在屏幕上和导出时的显示方式）由扩展配置提供——见下方的 [Setup](#setup)。如果没有它，选择某种格式不会产生任何可见效果。

## 安装

通过 Tiptap CLI 添加该组件：

```bash
npx @tiptap/cli@latest add numbering-format-dropdown-menu
```

## 设置

该组件只在列表上存储一个格式 **id**；实际的标记渲染由扩展负责。请通过 ConvertKit 配置 `orderedListNumbering`，为你想提供的每个格式 id 提供一个层级定义，并且同样的定义也可以传递给 `ExportDocx`，以实现无损往返。

```tsx
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'

const NUMBERING_FORMATS = [
  {
    id: 'decimal',
    levels: Array.from({ length: 9 }, (_v, depth) => ({
      baseStyle: ['decimal', 'lowerLetter', 'lowerRoman'][depth % 3],
      textTemplate: `%${depth + 1}.`,
    })),
  },
  // …你提供的每个 id 对应一个条目（见 NUMBERING_FORMAT_IDS）
]

const editor = useEditor({
  extensions: [
    ConvertKit.configure({
      orderedListNumbering: {
        formats: NUMBERING_FORMATS,
        defaultFormat: 'decimal',
      },
    }),
    // …
  ],
})
```

## 组件

### `<NumberingFormatDropdownMenu />`

一个预构建组件，将有序列表切换按钮与编号样式下拉菜单组合在一起。

#### 用法

```tsx
export default function MyEditor() {
  return (
    <NumberingFormatDropdownMenu
      editor={editor}
      hideWhenUnavailable={true}
      modal={false}
      onOpenChange={(isOpen) => console.log('Dropdown', isOpen ? 'opened' : 'closed')}
    />
  )
}
```

#### 属性

该组件还会将任何额外的 `Button` 属性（除 `type` 外）转发给下拉触发器。

| 名称                    | 类型                  | 默认值               | 描述                |
| --------------------- | ------------------- | ----------------- | ----------------- |
| `editor`              | `Editor \| null`    | `undefined`       | Tiptap 编辑器实例。     |
| `formats`             | `NumberingFormat[]` | `DEFAULT_FORMATS` | 在下拉菜单中提供的编号格式 id。 |
| `hideWhenUnavailable` | `boolean`           | `false`           | 当有序列表不可用时隐藏下拉菜单。  |
| `modal`               | `boolean`           | `true`            | 下拉菜单是否以模态方式捕获焦点。  |
| `onOpenChange`        | `(boolean) => void` | `undefined`       | 下拉菜单打开或关闭时的回调。    |

### `<NumberingFormatButton />`

单个格式选项，以小型嵌套列表预览的形式渲染。可用于构建下拉菜单网格，也可单独使用。

#### 属性

| 名称                    | 类型                | 默认值         | 描述                 |
| --------------------- | ----------------- | ----------- | ------------------ |
| `editor`              | `Editor \| null`  | `undefined` | Tiptap 编辑器实例。      |
| `format`              | `NumberingFormat` | —           | 此按钮应用的编号格式。**必填。** |
| `hideWhenUnavailable` | `boolean`         | `false`     | 当有序列表不可用时隐藏按钮。     |
| `onFormatSet`         | `() => void`      | `undefined` | 格式成功应用后调用。         |

## 钩子

### `useNumberingFormatDropdownMenu()`

一个无头钩子，提供构建自定义编号下拉菜单所需的完整状态和操作。

#### 用法

```tsx
function MyNumberingDropdown() {
  const {
    isVisible,
    currentFormat,
    canToggle,
    formats,
    setFormat,
    isFormatActive,
    getFormatLabel,
  } = useNumberingFormatDropdownMenu({ editor, hideWhenUnavailable: true })

  if (!isVisible) return null

  return (
    <DropdownMenu>
      <DropdownMenuTrigger disabled={!canToggle}>编号</DropdownMenuTrigger>
      <DropdownMenuContent>
        {formats.map((format) => (
          <DropdownMenuItem
            key={format}
            data-active-state={isFormatActive(format) ? 'on' : 'off'}
            onClick={() => setFormat(format)}
          >
            {getFormatLabel(format)}
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  )
}
```

#### 属性

| 名称                    | 类型                  | 默认值               | 描述               |
| --------------------- | ------------------- | ----------------- | ---------------- |
| `editor`              | `Editor \| null`    | `undefined`       | Tiptap 编辑器实例。    |
| `formats`             | `NumberingFormat[]` | `DEFAULT_FORMATS` | 提供的编号格式 ID。      |
| `hideWhenUnavailable` | `boolean`           | `false`           | 当有序列表不可用时隐藏下拉菜单。 |

#### 返回值

| 名称               | 类型                                     | 描述                                |
| ---------------- | -------------------------------------- | --------------------------------- |
| `isVisible`      | `boolean`                              | 下拉菜单是否应当渲染。                       |
| `currentFormat`  | `string`                               | 当前应用的格式 ID（如果未设置，则为 `"decimal"`）。 |
| `isActive`       | `boolean`                              | 提供的格式中是否有任意一个当前处于激活状态。            |
| `canToggle`      | `boolean`                              | 当前状态下是否可以设置编号格式。                  |
| `formats`        | `NumberingFormat[]`                    | 提供的格式 ID。                         |
| `setFormat`      | `(format: NumberingFormat) => boolean` | 应用某个格式；成功时返回 `true`。              |
| `isFormatActive` | `(format: NumberingFormat) => boolean` | 某个给定格式是否为当前激活格式（用于激活标记）。          |
| `getFormatLabel` | `(format: NumberingFormat) => string`  | 格式的可读预览标签，例如 `"1. 2. 3."`。        |

### `useNumberingFormatButton()`

单个格式选项的状态和处理器。

#### 属性

| 名称                    | 类型                | 默认值         | 描述               |
| --------------------- | ----------------- | ----------- | ---------------- |
| `editor`              | `Editor \| null`  | `undefined` | Tiptap 编辑器实例。    |
| `format`              | `NumberingFormat` | —           | 此按钮应用的格式。**必填。** |
| `hideWhenUnavailable` | `boolean`         | `false`     | 当不可用时隐藏按钮。       |
| `onFormatSet`         | `() => void`      | `undefined` | 格式设置后调用。         |

#### 返回值

| 名称                | 类型              | 描述                        |
| ----------------- | --------------- | ------------------------- |
| `isVisible`       | `boolean`       | 按钮是否应当渲染。                 |
| `isActive`        | `boolean`       | 此格式当前是否处于激活状态。            |
| `handleSetFormat` | `() => boolean` | 应用该格式；成功时返回 `true`。       |
| `canSet`          | `boolean`       | 当前状态下是否可以设置该格式。           |
| `label`           | `string`        | 该格式的预览标签，例如 `"1. 2. 3."`。 |

## 工具

### 格式化 id 和标签

```tsx
import {
  NUMBERING_FORMAT_IDS,
  NUMBERING_FORMAT_LABELS,
  DEFAULT_FORMATS,
} from '@/components/tiptap-ui/numbering-format-dropdown-menu'
```

`NumberingFormat` 是以下之一：`decimal`、`decimal-paren`、`decimal-nested`、`upper-alpha`、`lower-alpha`、`upper-roman`、`lower-roman`、`decimal-zero`。`NUMBERING_FORMAT_IDS` 按下拉菜单顺序列出它们；`DEFAULT_FORMATS` 是默认提供的集合；`NUMBERING_FORMAT_LABELS` 将每个 id 映射到其预览字符串（例如 `"A. B. C."`）。

### 编辑器辅助函数

```tsx
import {
  setNumberingFormat,
  isNumberingFormatActive,
  getCurrentNumberingFormat,
  canSetNumberingFormat,
  getFormatLabel,
} from '@/components/tiptap-ui/numbering-format-dropdown-menu'

setNumberingFormat(editor, 'upper-roman') // 应用该格式，返回布尔值
getCurrentNumberingFormat(editor) // 当前激活的格式 id，若不在列表中则为 null
isNumberingFormatActive(editor, 'decimal') // 布尔值
canSetNumberingFormat(editor) // 布尔值
getFormatLabel('lower-alpha') // "a. b. c."
```

## 需求

### 依赖项

- `@tiptap/react` — Tiptap React 核心集成
- `@tiptap-pro/extension-convert-kit` — 提供 `orderedListNumbering` 扩展，用于存储和渲染该格式

### 引用的组件

- `use-tiptap-editor`（hook）
- `list-button`（组件）
- `button`（原始组件）
- `button-group`（原始组件）
- `dropdown-menu`（原始组件）
- `tiptap-utils`（库）
- `chevron-down-icon`（图标）
