AI 光标
AiCaret 扩展会在 AI 当前插入内容的位置显示一个光标装饰。在流式操作期间,它提供实时的视觉反馈,类似于 协作光标扩展。
用法
从 @tiptap-pro/ai-toolkit 导入 AiCaret 扩展并添加到你的编辑器扩展中。
import { AiCaret, AiToolkit } from '@tiptap-pro/ai-toolkit'
const editor = useEditor({
extensions: [StarterKit, AiToolkit, AiCaret],
})光标会在流式操作(如 streamHtml、streamTool 和 tiptapEditWorkflow)期间自动显示,流处理完成后光标消失。
配置
你可以配置光标的超时时间、用户标签和渲染方式。
AiCaret.configure({
// 在最后一次更新后,光标保持可见的时间(毫秒)
timeout: 2000,
// 光标标签的用户信息
user: {
name: 'AI',
color: '#a5b4fc',
},
})选项
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
timeout | number | 2000 | 在最后一次更新后光标保持可见的时间(毫秒)。 |
user | { name: string, color: string } | { name: 'AI', color: '#a5b4fc' } | 光标标签中显示的名称和颜色。 |
render | (user: AiCaretUser) => HTMLElement | 内置渲染函数 | 用于自定义渲染光标 DOM 元素的函数。 |
CSS 样式
默认的渲染函数会创建一个带有类名 tiptap-ai-caret 的 DOM 元素和一个带有类名 tiptap-ai-caret__label 的标签。添加以下 CSS 以美化光标:
.tiptap .tiptap-ai-caret {
border-left: 1px solid #0d0d0d;
border-right: 1px solid #0d0d0d;
margin-left: -1px;
margin-right: -1px;
pointer-events: none;
position: relative;
word-break: normal;
}
.tiptap .tiptap-ai-caret__label {
border-radius: 3px 3px 3px 0;
color: #0d0d0d;
font-size: 12px;
font-style: normal;
font-weight: 600;
left: -1px;
line-height: normal;
padding: 0.1rem 0.3rem;
position: absolute;
top: -1.4em;
user-select: none;
white-space: nowrap;
}光标和标签的 border-color 及 background-color 会根据 user.color 选项内联设置。
自定义渲染
你可以提供一个自定义的 render 函数,完全控制光标的 DOM 元素。
AiCaret.configure({
render: (user) => {
const el = document.createElement('span')
el.className = 'my-custom-ai-caret'
el.style.borderColor = user.color
el.textContent = user.name
return el
},
})事件
AiCaret 扩展会通过 Tiptap 的事件 API 触发事件。你可以订阅这些事件,以响应光标的移动——例如,用自定义 UI 行为跟随 AI 的写作位置。
可用事件
| 事件 | 描述 | 载荷 |
|---|---|---|
aiCaret:positionChanged | 在流式传输或编辑操作期间,每当 AI 光标位置更新时触发。 | { position: number } |
position 值是一个 ProseMirror 文档位置,指向 AI 光标当前所在的位置。
订阅事件
使用 editor.on 监听事件,并在不再需要时使用 editor.off 取消订阅。
editor.on('aiCaret:positionChanged', ({ position }) => {
console.log('AI 光标移动到了位置', position)
})aiCaret:positionChanged 事件在流式传输期间可能会频繁触发——每个流式块都会触发一次。如果你的处理函数会执行开销较大的工作,建议使用 requestAnimationFrame 或像 lodash.throttle 这样的工具进行节流。