編輯器
Editor Suggestion Menu
輸入 / 觸發浮動選單;挑選指令執行對應動作。
安裝
Terminal
pnpm dlx shadcn-vue add @admin/editor-suggestion-menuimport type { EditorSuggestionMenuItem } from '@/registry/admin/ui/editor-suggestion-menu'import { AdminEditorSuggestionMenu } from '@/registry/admin/ui/editor-suggestion-menu'admin-editor-suggestion-menu 只依賴 @admin/editor-core(menu popup engine 與共用型別);handlers 由呼叫端顯式傳入,可搭 <AdminRichEditor> 或 base <AdminEditor> 使用。
用法
在 <admin-rich-editor v-slot="{ editor, handlers }"> slot 內加 <admin-editor-suggestion-menu :editor :handlers :items="...">。輸入 / 觸發 popup。
<script setup lang="ts">import type { JSONContent } from '@tiptap/core'import type { EditorSuggestionMenuItem } from '@/components/admin/editor-suggestion-menu'import { ref } from 'vue'import { cn } from '@/lib/utils'import { baseProseClass } from '@/components/admin/editor'import { AdminEditorSuggestionMenu } from '@/components/admin/editor-suggestion-menu'import { AdminEditorToolbar, defaultEditorItems } from '@/components/admin/editor-toolbar'import { AdminRichEditor, starterKitProseClass } from '@/components/admin/rich-editor'const value = ref<JSONContent | string>('<p>輸入 / 觸發 slash command menu</p>')const slashItems: EditorSuggestionMenuItem[] = [ { kind: 'heading', level: 1, label: '標題 1', description: '大標題' }, { kind: 'heading', level: 2, label: '標題 2', description: '中標題' }, { kind: 'heading', level: 3, label: '標題 3', description: '小標題' }, { kind: 'paragraph', label: '內文', description: '一般段落' }, { kind: 'bulletList', label: '項目清單' }, { kind: 'orderedList', label: '數字清單' }, { kind: 'blockquote', label: '引言' }]</script><template> <admin-rich-editor v-slot="{ editor, handlers }" v-model="value" :ui="{ base: cn(baseProseClass, starterKitProseClass) }" > <admin-editor-toolbar :editor :handlers="handlers" :items="defaultEditorItems" /> <admin-editor-suggestion-menu :editor :handlers="handlers" :items="slashItems" /> </admin-rich-editor></template>EditorSuggestionMenuItem 介面
type EditorSuggestionMenuItem = EditorItem & { label: string description?: string icon?: Component | string}EditorItem 是 admin-editor-core 定義的 discriminated union(admin-rich-editor 也有 re-export),涵蓋 mark / heading / link、12 個無參數 kind 與自訂 handler kind。它直接重用 toolbar items 的結構,寫過 toolbar 就會寫:
const slashItems: EditorSuggestionMenuItem[] = [ { kind: 'heading', level: 1, label: '標題 1' }, { kind: 'bulletList', label: '項目清單' }, { kind: 'blockquote', label: '引言' }]選定 item 後 SFC 內部會:
- 用
editor.chain().focus().deleteRange(range)刪掉/xxx觸發範圍 - 透過
props.handlers取出handler[item.kind](handlers由呼叫端顯式傳入,可取自<AdminRichEditor v-slot="{ editor, handlers }">或 base editor 情境的createDefaultHandlers()) - 呼叫
handler.execute(editor, item).run()
由於與 toolbar items 共用 kind dispatch,對應 extension 未啟用時,選取後不會有動作(不會報錯)。
鍵盤導航
由 useEditorMenu composable 提供,不需額外設定:
| 按鍵 | 行為 |
|---|---|
| ArrowUp / ArrowDown | 上下移動選取 |
| Enter / Tab | 確認選取 |
| Escape | 關閉 popup |
選取 label / separator type 的 item 會自動跳過。
與 toolbar items 共用結構
suggestion menu 的 :items 接受扁平或分組陣列。defaultEditorItems 是分組陣列,攤平後即可直接沿用:
const slashItems = defaultEditorItems .flat() .filter((item): item is EditorSuggestionMenuItem => 'kind' in item && typeof item.label === 'string' )API 參考
admin-editor-suggestion-menu
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
editor* | Editor | — | tiptap Editor instance(必填) |
handlers* | EditorHandlers | — | handler map(必填):決定各 kind 選定後執行的行為,由呼叫端顯式傳入 |
items* | EditorSuggestionMenuItem[] | EditorSuggestionMenuItem[][] | — | 候選清單(可為扁平或分組陣列) |
char | string | undefined | "/" | 觸發字元,預設 `/` |
pluginKey | string | undefined | "editorSuggestionMenu" | PM plugin key,預設 `editorSuggestionMenu`(同 editor 內多 menu 並存時 override) |
limit | number | undefined | 10 | 顯示筆數上限,預設 10 |
filterFields | string[] | undefined | ["label"] | filter 比對欄位,預設 `['label']` |
ignoreFilter | boolean | undefined | false | true 時跳過內建 fuzzy filter(外部已 filter 時使用) |
class | ClassValue | — | — |
* 代表必填
更新紀錄
- feat: 新增 tiptap editor 元件系列273a0d0