docs/(plugins)/(functionality)/tabbable.cn.mdx
最快捷的方式是使用 TabbableKit,它包含预配置的 TabbablePlugin 和智能查询逻辑,可避免与其他插件冲突。
import { createPlateEditor } from 'platejs/react';
import { TabbableKit } from '@/components/editor/plugins/tabbable-kit';
const editor = createPlateEditor({
plugins: [
// ...其他插件,
...TabbableKit,
],
});
npm install @platejs/tabbable
import { TabbablePlugin } from '@platejs/tabbable/react';
import { createPlateEditor } from 'platejs/react';
const editor = createPlateEditor({
plugins: [
// ...其他插件,
TabbablePlugin,
],
});
import { TabbablePlugin } from '@platejs/tabbable/react';
import { createPlateEditor } from 'platejs/react';
import { KEYS } from 'platejs';
const editor = createPlateEditor({
plugins: [
// ...其他插件,
TabbablePlugin.configure({
options: {
query: (event) => {
// 在列表或代码块中禁用
const inList = editor.api.some({ match: { type: KEYS.li } });
const inCodeBlock = editor.api.some({ match: { type: KEYS.codeBlock } });
return !inList && !inCodeBlock;
},
globalEventListener: true,
isTabbable: (tabbableEntry) =>
editor.api.isVoid(tabbableEntry.slateNode),
},
}),
],
});
options.query: 根据编辑器状态动态启用/禁用插件的函数options.globalEventListener: 为true时,将事件监听器添加到document而非编辑器options.isTabbable: 判断哪些元素应包含在标签顺序中的函数Tabbable插件可能会与处理Tab键的其他插件产生冲突,例如:
使用query选项在Tab键应由其他插件处理时禁用Tabbable插件:
query: (event) => {
const inList = editor.api.some({ match: { type: KEYS.li } });
const inCodeBlock = editor.api.some({ match: { type: KEYS.codeBlock } });
return !inList && !inCodeBlock;
},
如果使用缩进插件,可以仅在选中特定类型节点(如void节点)时启用Tabbable插件:
query: (event) => !!editor.api.some({
match: (node) => editor.api.isVoid(node),
}),
将为编辑器中的每个可聚焦DOM元素创建一个TabbableEntry,使用tabbable NPM包确定。然后使用isTabbable过滤可聚焦列表。
默认情况下,isTabbable仅对void Slate节点内的entry返回true。可以覆盖isTabbable以支持其他类型Slate节点中包含的DOM元素:
// 启用CUSTOM_ELEMENT内的可聚焦DOM元素
isTabbable: (tabbableEntry) => (
tabbableEntry.slateNode.type === CUSTOM_ELEMENT ||
editor.api.isVoid(tabbableEntry.slateNode)
),
某些情况下,可能需要允许用户从编辑器切换到外部渲染的DOM元素(如交互式弹出框)。
为此,覆盖insertTabbableEntries返回TabbableEntry对象数组,每个对象对应一个要包含在可聚焦列表中的外部DOM元素。TabbableEntry的slateNode和path应引用当DOM元素可聚焦时用户光标所在的Slate节点。
将globalEventListener选项设为true以确保Tabbable插件能将用户焦点返回到编辑器。
例如,如果DOM元素在选中链接时出现,slateNode和path应为该链接的节点。
// 将.my-popover内的按钮添加到可聚焦列表
globalEventListener: true,
insertTabbableEntries: (event) => {
const [selectedNode, selectedNodePath] = editor.api.node(editor.selection);
return [
...document.querySelectorAll('.my-popover > button'),
].map((domNode) => ({
domNode,
slateNode: selectedNode,
path: selectedNodePath,
}));
},
管理可聚焦元素间标签顺序的插件。
<API name="TabbablePlugin"> <APIOptions> <APIItem name="query" type="(event: KeyboardEvent) => boolean" optional> 动态启用/禁用插件。 - **默认值:** `() => true` </APIItem> <APIItem name="globalEventListener" type="boolean" optional> 将事件监听器添加到document而非编辑器。 - **默认值:** `false` </APIItem> <APIItem name="insertTabbableEntries" type="(event: KeyboardEvent) => TabbableEntry[]" optional> 添加编辑器外的额外可聚焦entry。 - **默认值:** `() => []` </APIItem> <APIItem name="isTabbable" type="(tabbableEntry: TabbableEntry) => boolean" optional> 判断元素是否应可聚焦。 - **默认值:** `(tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode)` </APIItem> </APIOptions> </API>定义可聚焦entry的属性。
<API name="TabbableEntry"> <APIAttributes> <APIItem name="domNode" type="HTMLElement"> 表示可聚焦entry的HTML元素。 </APIItem> <APIItem name="slateNode" type="TNode"> 对应的Slate节点。 </APIItem> <APIItem name="path" type="Path"> 文档中Slate节点的路径。 </APIItem> </APIAttributes> </API>