AIChatInput
AI 聊天输入框:基于 tiptap 富文本编辑器(内核 + svelte-tiptap 动态 import 懒加载,绝不进主 bundle)。阶段 1 富文本输入 + 发送(sendHotKey、canSend、generating 停止键)+ Upload 附件。阶段 2 references 引用条(可点击/删除/renderReference 覆盖)+ suggestions 建议浮层(聚焦弹出,↑↓/Enter/Esc/点击外部,renderSuggestionItem 覆盖)+ renderTopSlot。阶段 3 skills 技能面板(空编辑区按 skillHotKey 弹出,↑↓/Enter/Esc,选中插入 skill-slot 自定义节点并 onSkillChange)+ skill-slot NodeView(inline atom chip,含删除,用 svelte-tiptap SvelteNodeViewRenderer 渲染 SkillSlotNode.svelte)+ renderTemplate 模版面板(当前技能 hasTemplate 时展示模版按钮,点击弹出,setContent 填入)。阶段 4 renderConfigureArea 配置区(footer 左侧,放 AIChatInputConfigureSelect/Button/RadioButton 经 configure context 用 field 绑定)+ configureDefaultValue + onConfigureChange,配置值发送时并入 MessageContent.setup。onMessageSend 载荷对齐 Semi MessageContent(inputContents/attachments/references/setup)。headless(canSend/sendHotKey/MessageContent/doc→contents/suggestion 键盘/reference 归一/skill 归一/getSkillSlotHTML/skillHotKey 判定/configure setField-removeField)在 @chenzy-design/core,可单测。ref 方法 setContent/focusEditor/getText/getHTML/getEditor/clearContent/changeTemplateVisible/getConfigureValue。阶段 5 Adapter 桥(messageToChatInput → AIDialogueMessage 喂 AIChatDialogue;chatInputToChatCompletion → OpenAI ChatCompletion user message)为 core 纯函数,从 svelte 包透传。
如何引入
import { AIChatInput } from '@chenzy-design/svelte';基础输入
tiptap 富文本输入 + Enter 发送,onMessageSend 拿到 MessageContent。
最近发送:(尚未发送)
生成态与停止
generating 时发送键变停止键、Enter 不发送,onStopGenerate 中断。
状态:待发送
快捷键与附件
sendHotKey='shift+enter' + round + Upload 附件(onUploadChange)。
当前附件:0 个 · 最近发送:(尚未发送)
引用
references 引用条渲染于编辑区上方,可点击/删除(受控)。
最近点击的引用:(未点击)
建议
聚焦弹出建议面板,↑↓ 导航 / Enter 选中 / Esc 关闭。
已选建议:(点击输入框查看建议)
技能与模版
按 skillHotKey 唤起技能面板,选中插入 skill-slot 节点;hasTemplate 弹模版(含 select-slot 下拉 / input-slot 可编辑填空)。
已选技能:(按 / 唤起技能)
配置区
renderConfigureArea + Configure 子组件(模型/联网/深度思考/MCP 多选),值发送时进 setup。
发送时的 setup:{}
接入对话
messageToChatInput Adapter 把发送载荷转成 Message,喂给 AIChatDialogue 展示。
API 参考
AIChatInput
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
defaultContent | 初始内容(HTML 或纯文本,tiptap Content) | string | '' |
placeholder | 占位文本(缺省走 locale AIChatInput.placeholder) | string | undefined |
canSend | 是否可发送;未设置按内容/附件推断,显式设置以此为准 | boolean | undefined |
generating | 生成中:发送键变停止键,Enter 不发送 | boolean | false |
sendHotKey | 发送快捷键 | 'enter'|'shift+enter' | 'enter' |
showUploadButton | 是否展示上传按钮 | boolean | true |
uploadProps | 透传给内部 Upload 的 props | object | undefined |
round | 圆角样式(对齐 Semi round) | boolean | false |
extensions | 追加 tiptap extensions(StarterKit 之后) | unknown[] | [] |
transformer | 富文本节点归一覆盖(对齐 Semi transformer) | Map<string, (node)=>Content> | undefined |
references | 受控引用列表,渲染于编辑区上方(阶段 2) | AIChatInputReference[] | [] |
showReference | 是否展示引用条(阶段 2) | boolean | true |
suggestions | 建议列表,聚焦空编辑区弹出面板(阶段 2) | AIChatInputSuggestion[] | [] |
topSlotPosition | renderTopSlot 相对引用条位置(阶段 2) | 'top'|'bottom' | 'top' |
skills | 技能列表,空编辑区按 skillHotKey 弹面板(阶段 3) | AIChatInputSkill[] | [] |
skillHotKey | 触发技能面板的按键(阶段 3) | string | '/' |
showTemplateButton | 是否展示模版按钮(仅当前技能 hasTemplate 时生效,阶段 3) | boolean | true |
configureDefaultValue | 配置区初始值(阶段 4) | Record<string, unknown> | undefined |
showUploadFile | top area 展示上传附件列表 | boolean | true |
clearContentOnGenerating | generating false→true 时清空输入 | boolean | true |
Events
| 事件 | 载荷 | 说明 |
|---|---|---|
onContentChange | { text, html, json } | 内容变化 |
onMessageSend | MessageContent(inputContents/attachments/references) | 发送消息 |
onStopGenerate | () | 停止生成 |
onUploadChange | attachments | 上传附件变化 |
onReferenceClick | reference | 点击引用(阶段 2) |
onReferenceDelete | reference | 删除引用(阶段 2) |
onSuggestClick | suggestion | 选中建议;未提供时默认填入编辑器(阶段 2) |
onSkillChange | skill | 选中技能(阶段 3) |
onTemplateVisibleChange | visible | 模版面板显隐变化(阶段 3) |
onConfigureChange | (value, changed) | 配置区变更(阶段 4) |
onFocus | event | 编辑区聚焦 |
onBlur | event | 编辑区失焦 |
onPaste | files | 粘贴(携带剪贴板文件) |
Slots
| 名称 | 说明 |
|---|---|
renderActionArea | 自定义发送/停止按钮区 |
renderReference | 自定义单条引用渲染(阶段 2) |
renderSuggestionItem | 自定义单条建议渲染(阶段 2) |
renderTopSlot | 自定义 top slot 渲染(阶段 2) |
renderSkillItem | 自定义单条技能渲染(阶段 3) |
renderTemplate | 模版面板渲染(阶段 3) |
renderConfigureArea | footer 配置区渲染(放 Configure 子组件,阶段 4) |
renderUploadButton | 自定义上传按钮 UI(保留内置上传/粘贴逻辑) |
Methods
| 属性 | 类型 | 说明 |
|---|---|---|
setContent | — | 设置编辑器内容 |
focusEditor | — | 聚焦编辑器 |
getText | — | 取纯文本 |
getHTML | — | 取 HTML |
getEditor | — | 取 tiptap Editor 实例 |
clearContent | — | 清空编辑器内容 |
changeTemplateVisible | — | 显隐模版面板(阶段 3) |
getConfigureValue | — | 取当前配置区值(阶段 4) |
deleteContent | — | 删除编辑器中匹配 content.text 的一段 |
setContentWhileSaveTool | — | 设置内容但保留当前技能 slot 前缀 |
deleteUploadFile | — | 从附件列表删除一项 |
Accessibility
| ARIA role | 编辑区 role=textbox aria-multiline;建议/技能面板 role=listbox / 项 role=option aria-selected;模版按钮 aria-expanded;引用 chip 名称与删除为平级 button(避免 nested-interactive);skill-slot chip 含删除按钮;input-slot 可编辑填空空态显示 placeholder(aria-hidden);Configure.Mcp 下拉 role=menuitemcheckbox;aria-label 全走 i18n |
| 键盘交互 | Enter 发送(sendHotKey=enter,Shift+Enter 换行)Shift+Enter 发送;建议技能面板可见时 ↑↓ 环绕导航、Enter 选中高亮项、Esc 关闭;空编辑区按 skillHotKey 弹技能面板;IME 组字中不发送;generating 时 Enter 不发送 |
设计变量
| 变量 | 默认值 | 用法 |
|---|---|---|
--cd-ai-chat-input-motion-duration | var(--cd-motion-duration-fast) | 描边/按钮悬浮过渡时长 |