┌────────────────────────────────────────────────────────────────┐ │ 📄 shadcn/directory/udecode/plate/(guides)/plugin-shortcuts.cn │ └────────────────────────────────────────────────────────────────┘
╔══════════════════════════════════════════════════════════════════════════════════════════════╗
║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║
键盘快捷键是实现快速高效编辑工作流的关键。Plate 允许您轻松为编辑器插件定义和自定义快捷键。
在创建或配置插件时(例如使用 createPlatePlugin().extend({...}) 或 ExistingPlugin.configure({...})),您可以为任何插件添加或修改快捷键。快捷键定义在插件配置的 shortcuts 字段中。
有两种主要方式定义快捷键行为:
创建快捷键最直接的方式是将其关联到插件中已有的方法。这可以是 transform 方法 或 API 方法。transform 是修改编辑器状态的函数(例如切换标记、插入元素),而 API 方法提供其他功能。
操作步骤:
shortcuts 配置对象中的快捷键名称与方法名称匹配(例如名为 toggle 的快捷键会查找名为 toggle 的 transform,如果没有 transform 则查找名为 toggle 的 API 方法)。keys(按键组合)。当按下指定按键时,Plate 会自动找到并调用对应方法。
import { createPlatePlugin, Key } from 'platejs/react';
// 示例:包含 transform 和 API 的简化插件
export const MyDocumentPlugin = createPlatePlugin({
key: 'doc',
})
// 定义 editor.tf.doc.format()
.extendTransforms(({ editor, type }) => ({
format: () => {
editor.tf.normalize({ force: true });
},
}))
// 定义 editor.api.doc.format()
.extendApi(({ editor, type }) => ({
save: async () => {
// 保存文档
// await fetch(...);
},
}))
.extend({ // 或使用 .configure() 扩展现有插件
shortcuts: {
// 这会调用 editor.tf.doc.format()
format: {
keys: [[Key.Mod, Key.Shift, 'f']], // 例如 Cmd/Ctrl + Shift + F
},
// 这会调用 editor.api.doc.save()
save: {
keys: [[Key.Mod, 's']], // 例如 Cmd/Ctrl + S
},
},
});
<Callout type="info">
快捷键名称(例如示例中的 `toggle`)非常重要,Plate 用它来定位插件上的匹配方法。它首先查找 transform 方法,如果没有找到则回退到 API 方法。
</Callout>
对于需要更复杂逻辑、依赖键盘事件或没有与现有 transform 名称直接一对一映射的操作,您可以提供自定义 handler 函数。当快捷键激活时,此函数将被执行。
import { createPlatePlugin, Key } from 'platejs/react';
export const CustomLoggerPlugin = createPlatePlugin({
key: 'customLogger',
}).extend({
shortcuts: {
logEditorState: {
keys: [[Key.Mod, Key.Alt, 's']], // 例如 Cmd/Ctrl + Alt + S
handler: ({ editor, event, eventDetails }) => {
// 'editor' 是 PlateEditor 实例
// 'event' 是原始 KeyboardEvent
// 'eventDetails' 提供来自热键库的更多上下文
console.info('当前编辑器值:', editor.children);
console.info('按下的按键:', eventDetails.keys);
// 您可能希望阻止其他操作或浏览器默认行为
// event.preventDefault();
},
},
},
});
定义或配置快捷键时,可以在其配置对象中使用以下属性:
keys: 必填。 触发快捷键的按键组合。
'mod+b' 或使用 Key 枚举的数组以获得更明确的控制(例如 [[Key.Mod, Key.Shift, 'x']])。Key.Mod 是一种便捷方式,在 macOS 上指定 Cmd,在其他操作系统上指定 Ctrl。handler: (可选)当快捷键激活时调用的函数。其签名为:
({ editor: PlateEditor; event: KeyboardEvent; eventDetails: HotkeysEvent; }) => void;
如果省略 handler,Plate 将尝试调用与快捷键名称匹配的 transform。
注意:如果您的 transform 或 handler 返回 false(例如未处理),将不会调用 preventDefault,允许其他处理程序或浏览器默认行为接管。任何其他返回值将使用默认的 preventDefault 行为。preventDefault: (可选)布尔值。如果设置为 true,则阻止该按键组合的浏览器默认行为(例如 Mod+B 通常在浏览器中会加粗文本)。默认为 true。这适用于大多数编辑器特定的快捷键。设置为 false 如果您需要允许浏览器的默认行为或让其他处理程序处理事件,特别是如果您的处理程序可能不总是执行操作(例如在当前上下文中不应用的缩进命令)。priority: (可选)数字。如果多个插件为完全相同的 keys 定义了快捷键,具有更高 priority 数字的快捷键将优先。这对于解决冲突很有用。@udecode/react-hotkeys 库的 useHotkeys 钩子兼容的其他选项,例如 enabled、enableOnContentEditable 等,以微调行为。许多官方 Plate 插件为其常见操作预配置了快捷键。这些默认值通常链接到插件的内部 transform 方法。目前,以下基本标记插件包含默认快捷键:
Mod+BMod+IMod+U其他插件,如 CodePlugin、StrikethroughPlugin 等,提供可以轻松链接到快捷键的 transform(例如,toggle 快捷键将链接到 editor.tf.<pluginKey>.toggle()),但您需要为它们明确定义快捷键 keys。
单个插件不限于一个快捷键;您可以根据需要定义任意数量:
import { createPlatePlugin, Key } from 'platejs/react';
export const MyFormattingTools = createPlatePlugin({
key: 'myFormatting',
// 假设存在 transform 如 editor.tf.myFormatting.applyHeader
// 和 editor.tf.myFormatting.applyCodeStyle。
})
.extend({
shortcuts: {
applyHeader: {
keys: [[Key.Mod, Key.Alt, '1']],
},
applyCodeStyle: {
keys: [[Key.Mod, Key.Alt, 'c']],
},
// 带有自定义处理函数的快捷键
logSomething: {
keys: [[Key.Mod, 'l']],
handler: () => console.info('来自 MyFormattingTools 的日志记录!'),
},
},
});
如果多个快捷键(可能来自不同插件)配置为使用完全相同的按键组合(例如 Mod+Shift+P),快捷键配置对象中的 priority 属性决定执行哪个快捷键的操作。
数字越大优先级越高。如果未在快捷键上显式设置 priority,则使用其父插件的 priority 作为回退。这允许在按键组合重叠时精细控制哪个操作优先。
const PluginA = createPlatePlugin({ key: 'pluginA', priority: 10 }).extend({
shortcuts: {
doSomethingImportant: {
keys: 'mod+shift+p',
handler: () => console.info('插件 A: 在 Mod+Shift+P 上的重要操作!'),
priority: 100, // 显式,此特定快捷键的高优先级
}
}
});
const PluginB = createPlatePlugin({ key: 'pluginB', priority: 20 }).extend({
shortcuts: {
doSomethingLessImportant: {
keys: 'mod+shift+p', // 与 PluginA 的快捷键相同的按键组合
handler: () => console.info('插件 B: 在 Mod+Shift+P 上的不太重要的操作。'),
// 没有显式的快捷键优先级,将使用 PluginB 的优先级 (20)
}
}
});
// 如果两个插件都激活,按下 Mod+Shift+P 将执行 PluginA 的 'doSomethingImportant' 处理程序
// 因为其快捷键具有更高的优先级 (100 vs 20)。
在配置特定插件时,您可以更改或禁用其快捷键。
更改插件的快捷键:
在配置插件时(例如 BoldPlugin.configure({ ... })),您可以通过其名称(如 toggle)定义快捷键。如果插件已有该名称的快捷键(可能是默认的),您的新配置将用于该插件。您可以更改其 keys,提供新的 handler,或调整其他属性。
import { BoldPlugin, Key } from '@platejs/basic-nodes/react';
// BoldPlugin 有一个名为 'toggle' 的默认快捷键(通常是 Mod+B)。
// 让我们将 BoldPlugin 的按键组合更改为 Mod+Shift+B。
const MyCustomBoldPlugin = BoldPlugin.configure({
shortcuts: {
toggle: { // 这会重新配置 BoldPlugin 的 'toggle' 快捷键
keys: [[Key.Mod, Key.Shift, 'b']], // 新的按键组合
// 原始处理程序(链接到 'toggle' transform)通常会被保留
// 除非在此处指定新的 'handler'。
},
},
});
禁用插件的快捷键:
在该插件的 shortcuts 对象中将快捷键配置设置为 null。这将移除该特定快捷键(例如 ItalicPlugin 的 toggle)。
import { ItalicPlugin } from '@platejs/basic-nodes/react';
// 示例:禁用 ItalicPlugin 的 'toggle' 快捷键
const MyCustomItalicPlugin = ItalicPlugin.configure({
shortcuts: {
toggle: null, // 这将移除/禁用 ItalicPlugin 的 'toggle' 快捷键。
},
});
除了插件特定的快捷键,您还可以在使用 createPlateEditor 创建编辑器时直接在编辑器实例上定义全局快捷键。这些快捷键的行为类似于插件快捷键。
import { createPlateEditor, Key } from 'platejs/react';
const editor = createPlateEditor({
plugins: [/* ...您的插件数组... */],
shortcuts: {
// 全局快捷键,可能用于保存文档
saveDocument: {
keys: [[Key.Mod, 's']],
handler: ({ editor, event }) => {
console.info('尝试保存文档内容:', editor.children);
// 由于此快捷键的 preventDefault 设置为 false,
// 浏览器的保存对话框将默认出现。
// 如果您想有条件地阻止浏览器的默认行为
// (例如,仅在满足某些条件时阻止保存),
// 您可以在处理程序中根据需要调用 event.preventDefault():
// if (shouldPrevent) event.preventDefault();
},
preventDefault: false,
},
anotherGlobalAction: {
keys: [[Key.Ctrl, Key.Alt, 'g']],
handler: () => alert('全局操作触发!'),
}
},
});
编辑器级别的快捷键通常具有较高的默认优先级,但如果存在冲突,仍可能受到单个插件快捷键的 priority 设置的影响。
preventDefault:大多数编辑器快捷键应阻止该按键组合的浏览器默认行为。Plate 通过默认将 preventDefault 设置为 true 来处理此问题。您通常不需要显式设置它。但是,如果您的快捷键处理程序有条件地执行操作(例如仅在满足某些条件时应用的缩进命令),并且您希望在其他操作不运行时让其他处理程序或浏览器的默认行为接管,请为该快捷键设置 preventDefault: false。priority 属性明确定义哪个快捷键应优先。║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║
╚══════════════════════════════════════════════════════════════════════════════════════════════╝