@composy/chat-core 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/README.md +187 -123
  2. package/dist/index.js +2018 -1035
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.min.js +1370 -1644
  5. package/dist/index.min.js.map +1 -0
  6. package/es/.dts-output-manifest.json +1 -0
  7. package/es/.dts.tsbuildinfo +1 -0
  8. package/es/constants/dom.d.ts +3 -19
  9. package/es/constants/dom.js +4 -4
  10. package/es/constants/dom.js.map +1 -1
  11. package/es/core/chat-manager.d.ts +33 -22
  12. package/es/core/chat-manager.js +174 -50
  13. package/es/core/chat-manager.js.map +1 -1
  14. package/es/core/event-emitter.d.ts +0 -1
  15. package/es/core/event-emitter.js +14 -7
  16. package/es/core/event-emitter.js.map +1 -1
  17. package/es/core/mention-engine.d.ts +1 -2
  18. package/es/core/mention-engine.js +9 -9
  19. package/es/core/mention-engine.js.map +1 -1
  20. package/es/core/message-schema.d.ts +19 -0
  21. package/es/core/message-schema.js +197 -0
  22. package/es/core/message-schema.js.map +1 -0
  23. package/es/core/outbox.d.ts +63 -0
  24. package/es/core/outbox.js +160 -0
  25. package/es/core/outbox.js.map +1 -0
  26. package/es/core/transport.d.ts +79 -0
  27. package/es/core/transport.js +102 -0
  28. package/es/core/transport.js.map +1 -0
  29. package/es/index.d.ts +12 -7
  30. package/es/index.js +167 -36
  31. package/es/index.js.map +1 -1
  32. package/es/renderer/dom-renderer.d.ts +16 -4
  33. package/es/renderer/dom-renderer.js +316 -61
  34. package/es/renderer/dom-renderer.js.map +1 -1
  35. package/es/renderer/style-manager.d.ts +14 -38
  36. package/es/renderer/style-manager.js +92 -63
  37. package/es/renderer/style-manager.js.map +1 -1
  38. package/es/theme/theme-manager.d.ts +4 -3
  39. package/es/theme/theme-manager.js +19 -9
  40. package/es/theme/theme-manager.js.map +1 -1
  41. package/es/theme/tokens.d.ts +0 -1
  42. package/es/theme/tokens.js +92 -92
  43. package/es/theme/tokens.js.map +1 -1
  44. package/es/types/index.d.ts +104 -24
  45. package/es/types/index.js +8 -3
  46. package/es/types/index.js.map +1 -0
  47. package/esm/constants/dom.d.ts +3 -19
  48. package/esm/constants/dom.js +4 -4
  49. package/esm/constants/dom.js.map +1 -1
  50. package/esm/core/chat-manager.d.ts +33 -22
  51. package/esm/core/chat-manager.js +174 -50
  52. package/esm/core/chat-manager.js.map +1 -1
  53. package/esm/core/event-emitter.d.ts +0 -1
  54. package/esm/core/event-emitter.js +14 -7
  55. package/esm/core/event-emitter.js.map +1 -1
  56. package/esm/core/mention-engine.d.ts +1 -2
  57. package/esm/core/mention-engine.js +9 -9
  58. package/esm/core/mention-engine.js.map +1 -1
  59. package/esm/core/message-schema.d.ts +19 -0
  60. package/esm/core/message-schema.js +197 -0
  61. package/esm/core/message-schema.js.map +1 -0
  62. package/esm/core/outbox.d.ts +63 -0
  63. package/esm/core/outbox.js +160 -0
  64. package/esm/core/outbox.js.map +1 -0
  65. package/esm/core/transport.d.ts +79 -0
  66. package/esm/core/transport.js +102 -0
  67. package/esm/core/transport.js.map +1 -0
  68. package/esm/index.d.ts +12 -7
  69. package/esm/index.js +169 -38
  70. package/esm/index.js.map +1 -1
  71. package/esm/renderer/dom-renderer.d.ts +16 -4
  72. package/esm/renderer/dom-renderer.js +316 -61
  73. package/esm/renderer/dom-renderer.js.map +1 -1
  74. package/esm/renderer/style-manager.d.ts +14 -38
  75. package/esm/renderer/style-manager.js +92 -63
  76. package/esm/renderer/style-manager.js.map +1 -1
  77. package/esm/theme/theme-manager.d.ts +4 -3
  78. package/esm/theme/theme-manager.js +19 -9
  79. package/esm/theme/theme-manager.js.map +1 -1
  80. package/esm/theme/tokens.d.ts +0 -1
  81. package/esm/theme/tokens.js +92 -92
  82. package/esm/theme/tokens.js.map +1 -1
  83. package/esm/types/index.d.ts +104 -24
  84. package/esm/types/index.js +8 -3
  85. package/esm/types/index.js.map +1 -0
  86. package/lib/constants/dom.cjs +4 -4
  87. package/lib/constants/dom.cjs.map +1 -1
  88. package/lib/constants/dom.d.cts +25 -0
  89. package/lib/constants/dom.d.ts +3 -19
  90. package/lib/core/chat-manager.cjs +174 -50
  91. package/lib/core/chat-manager.cjs.map +1 -1
  92. package/lib/core/chat-manager.d.cts +45 -0
  93. package/lib/core/chat-manager.d.ts +33 -22
  94. package/lib/core/event-emitter.cjs +14 -7
  95. package/lib/core/event-emitter.cjs.map +1 -1
  96. package/lib/core/event-emitter.d.cts +47 -0
  97. package/lib/core/event-emitter.d.ts +0 -1
  98. package/lib/core/mention-engine.cjs +9 -9
  99. package/lib/core/mention-engine.cjs.map +1 -1
  100. package/lib/core/mention-engine.d.cts +40 -0
  101. package/lib/core/mention-engine.d.ts +1 -2
  102. package/lib/core/message-schema.cjs +202 -0
  103. package/lib/core/message-schema.cjs.map +1 -0
  104. package/lib/core/message-schema.d.cts +19 -0
  105. package/lib/core/message-schema.d.ts +19 -0
  106. package/lib/core/outbox.cjs +162 -0
  107. package/lib/core/outbox.cjs.map +1 -0
  108. package/lib/core/outbox.d.cts +63 -0
  109. package/lib/core/outbox.d.ts +63 -0
  110. package/lib/core/transport.cjs +103 -0
  111. package/lib/core/transport.cjs.map +1 -0
  112. package/lib/core/transport.d.cts +79 -0
  113. package/lib/core/transport.d.ts +79 -0
  114. package/lib/index.cjs +175 -35
  115. package/lib/index.cjs.map +1 -1
  116. package/lib/index.d.cts +33 -0
  117. package/lib/index.d.ts +12 -7
  118. package/lib/renderer/dom-renderer.cjs +316 -61
  119. package/lib/renderer/dom-renderer.cjs.map +1 -1
  120. package/lib/renderer/dom-renderer.d.cts +91 -0
  121. package/lib/renderer/dom-renderer.d.ts +16 -4
  122. package/lib/renderer/style-manager.cjs +92 -62
  123. package/lib/renderer/style-manager.cjs.map +1 -1
  124. package/lib/renderer/style-manager.d.cts +34 -0
  125. package/lib/renderer/style-manager.d.ts +14 -38
  126. package/lib/theme/theme-manager.cjs +19 -9
  127. package/lib/theme/theme-manager.cjs.map +1 -1
  128. package/lib/theme/theme-manager.d.cts +34 -0
  129. package/lib/theme/theme-manager.d.ts +4 -3
  130. package/lib/theme/tokens.cjs +92 -92
  131. package/lib/theme/tokens.cjs.map +1 -1
  132. package/lib/theme/tokens.d.cts +56 -0
  133. package/lib/theme/tokens.d.ts +0 -1
  134. package/lib/types/index.cjs +8 -3
  135. package/lib/types/index.cjs.map +1 -0
  136. package/lib/types/index.d.cts +284 -0
  137. package/lib/types/index.d.ts +104 -24
  138. package/package.json +16 -13
  139. package/es/constants/dom.d.ts.map +0 -1
  140. package/es/core/chat-manager.d.ts.map +0 -1
  141. package/es/core/event-emitter.d.ts.map +0 -1
  142. package/es/core/mention-engine.d.ts.map +0 -1
  143. package/es/index.d.ts.map +0 -1
  144. package/es/renderer/dom-renderer.d.ts.map +0 -1
  145. package/es/renderer/style-manager.d.ts.map +0 -1
  146. package/es/theme/theme-manager.d.ts.map +0 -1
  147. package/es/theme/tokens.d.ts.map +0 -1
  148. package/es/types/index.d.ts.map +0 -1
  149. package/esm/constants/dom.d.ts.map +0 -1
  150. package/esm/core/chat-manager.d.ts.map +0 -1
  151. package/esm/core/event-emitter.d.ts.map +0 -1
  152. package/esm/core/mention-engine.d.ts.map +0 -1
  153. package/esm/index.d.ts.map +0 -1
  154. package/esm/renderer/dom-renderer.d.ts.map +0 -1
  155. package/esm/renderer/style-manager.d.ts.map +0 -1
  156. package/esm/theme/theme-manager.d.ts.map +0 -1
  157. package/esm/theme/tokens.d.ts.map +0 -1
  158. package/esm/types/index.d.ts.map +0 -1
  159. package/lib/constants/dom.d.ts.map +0 -1
  160. package/lib/core/chat-manager.d.ts.map +0 -1
  161. package/lib/core/event-emitter.d.ts.map +0 -1
  162. package/lib/core/mention-engine.d.ts.map +0 -1
  163. package/lib/index.d.ts.map +0 -1
  164. package/lib/renderer/dom-renderer.d.ts.map +0 -1
  165. package/lib/renderer/style-manager.d.ts.map +0 -1
  166. package/lib/theme/theme-manager.d.ts.map +0 -1
  167. package/lib/theme/tokens.d.ts.map +0 -1
  168. package/lib/types/index.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.min.js","names":["clone","message","row","entry"],"sources":["../src/constants/dom.ts","../src/types/index.ts","../src/core/message-schema.ts","../src/core/chat-manager.ts","../src/core/event-emitter.ts","../src/core/mention-engine.ts","../src/core/transport.ts","../src/renderer/style-manager.ts","../src/renderer/dom-renderer.ts","../src/theme/tokens.ts","../src/theme/theme-manager.ts","../src/core/outbox.ts","../src/index.ts"],"sourcesContent":["/**\r\n * @file dom.ts\r\n * @description dom 模块\r\n */\r\n\r\nexport const DEFAULT_CLASS_PREFIX = 'ldesign-chat'\r\nexport const COMPONENT_CSS_VAR_PREFIX = '--ldesign-chat'\r\nexport const STYLE_ELEMENT_ID = 'ldesign-chat-styles'\r\n\r\n/**\r\n * normalizeClassPrefix - normalize Class Prefix function\r\n * @param prefix - Optional class prefix\r\n * @returns 返回值说明\r\n */\r\nexport function normalizeClassPrefix(prefix?: string): string {\r\n const trimmed = prefix?.trim()\r\n if (!trimmed) return DEFAULT_CLASS_PREFIX\r\n\r\n const withoutNamespace = trimmed\r\n .replace(/^ldesign-/i, '')\r\n .replace(/[^\\w-]+/g, '-')\r\n const safeSuffix = withoutNamespace.replace(/-+/g, '-').replace(/^-|-$/g, '')\r\n return safeSuffix ? `ldesign-${safeSuffix}` : DEFAULT_CLASS_PREFIX\r\n}\r\n\r\n/**\r\n * getStyleElementId - get Style Element Id function\r\n * @param prefix - Class prefix\r\n * @returns 返回值说明\r\n */\r\nexport function getStyleElementId(prefix = DEFAULT_CLASS_PREFIX): string {\r\n const normalized = normalizeClassPrefix(prefix)\r\n return normalized === DEFAULT_CLASS_PREFIX\r\n ? STYLE_ELEMENT_ID\r\n : `${normalized}-styles`\r\n}\r\n\r\n/**\r\n * cx - cx function\r\n * @param classes - Class names to join\r\n * @returns 返回值说明\r\n */\r\nexport function cx(...classes: (string | false | null | undefined)[]): string {\r\n return classes.filter(Boolean).join(' ')\r\n}\r\n","/**\r\n * @composy/chat-core types\r\n */\r\n\r\n// ==================== 消息相关 ====================\r\n\r\n/** 消息类型 */\r\nexport type MessageType = 'text' | 'image' | 'file' | 'system' | 'custom'\r\n\r\n/** 工具栏按钮类型 */\r\nexport type ToolbarAction = 'image' | 'file' | 'voice'\r\n\r\n/** 消息发送状态 */\r\nexport type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed'\r\n\r\n/** 消息方向 */\r\nexport type MessageDirection = 'incoming' | 'outgoing'\r\n\r\n/** 用户信息 */\r\nexport interface ChatUser {\r\n /** 用户 ID */\r\n id: string\r\n /** 昵称 */\r\n nickname: string\r\n /** 头像 URL */\r\n avatar?: string\r\n}\r\n\r\n/** @提及项 */\r\nexport interface MentionItem {\r\n /** 用户 ID */\r\n id: string\r\n /** 显示名称 */\r\n name: string\r\n /** 头像 */\r\n avatar?: string\r\n}\r\n\r\n/** 文件附件 */\r\nexport interface FileAttachment {\r\n /** 文件名 */\r\n name: string\r\n /** 文件大小(字节) */\r\n size: number\r\n /** 文件 URL */\r\n url: string\r\n /** MIME 类型 */\r\n mimeType?: string\r\n}\r\n\r\n/** 图片附件 */\r\nexport interface ImageAttachment {\r\n /** 图片 URL */\r\n url: string\r\n /** 缩略图 URL */\r\n thumbUrl?: string\r\n /** 宽度 */\r\n width?: number\r\n /** 高度 */\r\n height?: number\r\n}\r\n\r\n/** 结构化消息内容块。未知块应在上游归一化时降级,不得直接执行 HTML。 */\r\nexport type ChatContentBlock =\r\n | { type: 'text'; text: string }\r\n | { type: 'mention'; id: string; label: string }\r\n | { type: 'link'; url: string; label?: string }\r\n | { type: 'code'; code: string; language?: string }\r\n | {\r\n type: 'image'\r\n src: string\r\n alt?: string\r\n width?: number\r\n height?: number\r\n }\r\n | {\r\n type: 'file'\r\n url: string\r\n name: string\r\n size?: number\r\n mimeType?: string\r\n }\r\n | { type: 'break' }\r\n | {\r\n type: 'custom'\r\n kind: string\r\n data: Record<string, unknown>\r\n fallback?: string\r\n }\r\n\r\n/** 当前消息 schema 版本。 */\r\nexport const CHAT_MESSAGE_SCHEMA_VERSION = 1\r\n\r\n/** 聊天消息 */\r\nexport interface ChatMessage {\r\n /** 消息唯一 ID */\r\n id: string\r\n /** 消息类型 */\r\n type: MessageType\r\n /** 消息方向 */\r\n direction: MessageDirection\r\n /** 发送者信息 */\r\n sender: ChatUser\r\n /** 文本内容(text 类型) */\r\n content?: string\r\n /** 图片附件(image 类型) */\r\n image?: ImageAttachment\r\n /** 文件附件(file 类型) */\r\n file?: FileAttachment\r\n /** 自定义数据(custom 类型) */\r\n customData?: Record<string, unknown>\r\n /** 自定义 HTML(custom 类型);渲染时会过滤脚本、事件属性、样式和不安全 URL,仅保留受支持的基础标签 */\r\n customHtml?: string\r\n /** 提及列表 */\r\n mentions?: MentionItem[]\r\n /** 发送状态 */\r\n status?: MessageStatus\r\n /** 消息时间戳(毫秒) */\r\n timestamp: number\r\n /** 是否已撤回 */\r\n revoked?: boolean\r\n /** 是否正在流式输出(AI 风格) */\r\n streaming?: boolean\r\n /** 规范化内容块;未提供时使用 content/image/file 等兼容字段。 */\r\n contentBlocks?: ChatContentBlock[]\r\n /** 消息 schema 版本,便于跨 transport 与持久化迁移。 */\r\n schemaVersion?: number\r\n /** 会话标识,用于多会话 transport 复用。 */\r\n conversationId?: string\r\n /** 客户端幂等标识,服务端 ack 与离线 outbox 使用。 */\r\n clientMessageId?: string\r\n /** 服务端单调序号,用于乱序与重复消息过滤。 */\r\n sequence?: number\r\n /** 服务端同步游标。 */\r\n cursor?: string\r\n}\r\n\r\n// ==================== 主题相关 ====================\r\n\r\n/** 主题模式 */\r\nexport type ThemeMode = 'light' | 'dark' | 'auto'\r\n\r\n// ==================== 工具栏配置 ====================\r\n\r\n/** 工具栏配置 */\r\nexport interface ToolbarConfig {\r\n /** 启用图片上传按钮 */\r\n image?: boolean\r\n /** 启用文件上传按钮 */\r\n file?: boolean\r\n /** 启用语音输入按钮 */\r\n voice?: boolean\r\n}\r\n\r\n// ==================== 配置相关 ====================\r\n\r\n/** 聊天组件配置 */\r\nexport interface ChatConfig {\r\n /** 挂载容器 */\r\n container: HTMLElement | string\r\n /** 当前用户 ID(用于判断消息方向) */\r\n currentUserId: string\r\n /** 初始消息列表 */\r\n messages?: ChatMessage[]\r\n /** 主题模式 */\r\n theme?: ThemeMode\r\n /** 是否显示头像 */\r\n showAvatar?: boolean\r\n /** 是否显示昵称 */\r\n showNickname?: boolean\r\n /** 是否显示时间 */\r\n showTimestamp?: boolean\r\n /** 时间分组间隔(毫秒),默认 300000 (5分钟) */\r\n timeGroupInterval?: number\r\n /** 是否显示消息状态 */\r\n showStatus?: boolean\r\n /** 是否显示输入框 */\r\n showInput?: boolean\r\n /** 输入框占位文本 */\r\n inputPlaceholder?: string\r\n /** 是否启用 @提及 */\r\n enableMention?: boolean\r\n /** @提及候选人列表 */\r\n mentionMembers?: MentionItem[]\r\n /** 是否支持加载更多 */\r\n enableLoadMore?: boolean\r\n /** 加载更多文本 */\r\n loadMoreText?: string\r\n /** CSS class 前缀 */\r\n classPrefix?: string\r\n enterToSend?: boolean\r\n clearInputOnSend?: boolean\r\n maxInputLength?: number\r\n voiceLang?: string\r\n /** 日期格式化函数 */\r\n formatTime?: (timestamp: number) => string\r\n /** 是否启用工具栏 */\r\n enableToolbar?: boolean\r\n /** 工具栏配置 */\r\n toolbarConfig?: ToolbarConfig\r\n /** 可选消息 transport;不配置时 Core 仍保持纯本地模式。 */\r\n transport?: import('../core/transport').ChatTransport\r\n /** transport 使用的会话标识。 */\r\n conversationId?: string\r\n /** 创建实例后自动连接 transport。 */\r\n autoConnect?: boolean\r\n /** transport 初始同步游标。 */\r\n transportCursor?: string\r\n /** 可选离线 outbox,用于保存发送中的消息并在连接恢复后重试。 */\r\n outbox?: import('../core/outbox').ChatOutbox\r\n\r\n // 回调\r\n /** 发送消息回调 */\r\n onSend?: (content: string, mentions: MentionItem[]) => void\r\n /** 加载更多回调 */\r\n onLoadMore?: () => void | Promise<void>\r\n /** 消息点击回调 */\r\n onMessageClick?: (message: ChatMessage) => void\r\n /** @提及选择回调 */\r\n onMentionSelect?: (member: MentionItem) => void\r\n /** 图片上传回调(接收 File 列表) */\r\n onImageUpload?: (files: File[]) => void\r\n /** 文件上传回调(接收 File 列表) */\r\n onFileUpload?: (files: File[]) => void\r\n /** 粘贴回调(接收文件列表) */\r\n onPaste?: (files: File[]) => void\r\n /** 拖放回调(接收文件列表) */\r\n onDrop?: (files: File[]) => void\r\n /** 语音开始回调 */\r\n onVoiceStart?: () => void\r\n /** 语音结束回调(接收识别文本) */\r\n onVoiceEnd?: (transcript: string) => void\r\n onVoiceUnsupported?: () => void\r\n onVoiceError?: (error: unknown) => void\r\n onInputChange?: (content: string) => void\r\n}\r\n\r\n/** 聊天实例 */\r\nexport interface ChatInstance {\r\n /** 添加消息 */\r\n addMessage: (message: ChatMessage) => void\r\n /** 批量添加消息(在列表顶部插入,用于加载更多) */\r\n prependMessages: (messages: ChatMessage[]) => void\r\n /** 更新消息 */\r\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void\r\n /** 删除消息 */\r\n removeMessage: (id: string) => void\r\n /** 设置完整消息列表 */\r\n setMessages: (messages: ChatMessage[]) => void\r\n /** 清空所有消息 */\r\n clearMessages: () => void\r\n /** 滚动到底部 */\r\n scrollToBottom: (smooth?: boolean) => void\r\n /** 设置主题 */\r\n setTheme: (theme: ThemeMode) => void\r\n /** 更新 @提及候选人 */\r\n setMentionMembers: (members: MentionItem[]) => void\r\n /** 设置加载更多状态 */\r\n setLoadingMore: (loading: boolean) => void\r\n /** 聚焦输入框 */\r\n focusInput: () => void\r\n /** 设置输入框内容 */\r\n setInputContent: (content: string) => void\r\n /** 获取输入框内容 */\r\n getInputContent: () => string\r\n clearInput: () => void\r\n isAtBottom: (threshold?: number) => boolean\r\n /** 监听事件 */\r\n on: (event: string, handler: (...args: unknown[]) => void) => () => void\r\n /** 获取所有消息 */\r\n getMessages: () => ChatMessage[]\r\n /** 追加流式消息内容(AI 模式);可用 generation/sequence 防止旧 chunk 覆盖新流。 */\r\n appendMessageContent: (\r\n id: string,\r\n chunk: string,\r\n options?: { generation?: string; sequence?: number }\r\n ) => boolean\r\n /** 完成流式消息 */\r\n finishStreaming: (id: string, generation?: string) => boolean\r\n /** 开始一个新的流式 generation,旧 generation 的 chunk 会被丢弃。 */\r\n beginStreaming: (id: string, generation?: string) => string | null\r\n /** 取消当前流式 generation。 */\r\n cancelStreaming: (id: string, generation?: string) => boolean\r\n /** 合并远端消息,按消息 ID/clientMessageId 去重并按 sequence 忽略旧版本。 */\r\n mergeMessage: (\r\n message: ChatMessage,\r\n sequence?: number\r\n ) => 'added' | 'updated' | 'ignored'\r\n /** 连接 transport。 */\r\n connectTransport: (signal?: AbortSignal) => Promise<void>\r\n /** 断开 transport。 */\r\n disconnectTransport: () => Promise<void>\r\n /** 获取当前 transport 状态。 */\r\n getTransportStatus: () => import('../core/transport').ChatTransportStatus\r\n /** 通过 transport 发送消息,失败时保留 failed 状态并交给 outbox 重试。 */\r\n sendMessage: (\r\n message: ChatMessage,\r\n options?: { signal?: AbortSignal }\r\n ) => Promise<import('../core/transport').ChatTransportAck | void>\r\n /** 刷新离线 outbox。 */\r\n flushOutbox: (\r\n options?: import('../core/outbox').ChatOutboxFlushOptions\r\n ) => Promise<import('../core/outbox').ChatOutboxFlushResult>\r\n getMessage: (id: string) => ChatMessage | undefined\r\n /** 销毁实例 */\r\n destroy: () => void\r\n}\r\n","import type {\n ChatContentBlock,\n ChatMessage,\n ChatUser,\n FileAttachment,\n ImageAttachment,\n MentionItem,\n} from '../types'\nimport { CHAT_MESSAGE_SCHEMA_VERSION } from '../types'\n\n/**\n * 归一化消息并复制所有可变字段。\n *\n * 该函数是 transport、outbox、ChatManager 共享的边界:外部数据先经过\n * schema/version 校验,再进入内存状态,避免调用方继续修改内部消息。\n */\nexport function normalizeChatMessage(message: ChatMessage): ChatMessage {\n if (!message || typeof message !== 'object') {\n throw new TypeError('Chat message must be an object.')\n }\n if (typeof message.id !== 'string' || !message.id.trim()) {\n throw new TypeError('Chat message ID must be a non-empty string.')\n }\n if (!Number.isFinite(message.timestamp)) {\n throw new TypeError('Chat message timestamp must be finite.')\n }\n const schemaVersion = message.schemaVersion ?? CHAT_MESSAGE_SCHEMA_VERSION\n if (schemaVersion > CHAT_MESSAGE_SCHEMA_VERSION) {\n throw new Error(\n `Unsupported chat message schema version: ${schemaVersion}.`\n )\n }\n\n return cloneChatMessage({\n ...message,\n schemaVersion: CHAT_MESSAGE_SCHEMA_VERSION,\n ...(message.contentBlocks && {\n contentBlocks: normalizeChatContentBlocks(message.contentBlocks),\n }),\n })\n}\n\n/**\n * 对来自网络/持久化的 content block 做运行时白名单归一化。\n * 不认识的块优先使用 fallback 文本,否则丢弃,避免将任意对象带入渲染器。\n */\nexport function normalizeChatContentBlocks(\n blocks: unknown[]\n): ChatContentBlock[] {\n const normalized: ChatContentBlock[] = []\n for (const value of blocks) {\n const block = normalizeContentBlock(value)\n if (block) normalized.push(block)\n }\n return normalized\n}\n\n/** 归一化消息集合,并在进入状态层前拒绝重复的消息 ID/client ID。 */\nexport function normalizeChatMessages(messages: ChatMessage[]): ChatMessage[] {\n const result: ChatMessage[] = []\n const ids = new Set<string>()\n const clientIds = new Set<string>()\n for (const message of messages) {\n const normalized = normalizeChatMessage(message)\n if (ids.has(normalized.id)) {\n throw new Error(`Duplicate chat message ID: ${normalized.id}`)\n }\n if (\n normalized.clientMessageId &&\n clientIds.has(normalized.clientMessageId)\n ) {\n throw new Error(\n `Duplicate chat client message ID: ${normalized.clientMessageId}`\n )\n }\n ids.add(normalized.id)\n if (normalized.clientMessageId) clientIds.add(normalized.clientMessageId)\n result.push(normalized)\n }\n return result\n}\n\n/** 复制消息,用于事件 payload、outbox 与公开读取,避免可变引用泄漏。 */\nexport function cloneChatMessage(message: ChatMessage): ChatMessage {\n return {\n ...message,\n sender: cloneUser(message.sender),\n ...(message.image && { image: cloneImage(message.image) }),\n ...(message.file && { file: cloneFile(message.file) }),\n ...(message.mentions && {\n mentions: message.mentions.map(cloneMention),\n }),\n ...(message.contentBlocks && {\n contentBlocks: message.contentBlocks.map(cloneContentBlock),\n }),\n ...(message.customData && {\n customData: cloneRecord(message.customData),\n }),\n }\n}\n\n/** 根据服务端 sequence/timestamp 给出稳定排序值。 */\nexport function compareChatMessages(left: ChatMessage, right: ChatMessage) {\n if (\n Number.isFinite(left.sequence) &&\n Number.isFinite(right.sequence) &&\n left.sequence !== right.sequence\n ) {\n return (left.sequence as number) - (right.sequence as number)\n }\n if (left.timestamp !== right.timestamp)\n return left.timestamp - right.timestamp\n return left.id.localeCompare(right.id)\n}\n\nfunction cloneContentBlock(block: ChatContentBlock): ChatContentBlock {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text }\n case 'mention':\n return { type: 'mention', id: block.id, label: block.label }\n case 'link':\n return {\n type: 'link',\n url: block.url,\n ...(block.label && { label: block.label }),\n }\n case 'code':\n return {\n type: 'code',\n code: block.code,\n ...(block.language && { language: block.language }),\n }\n case 'image':\n return {\n type: 'image',\n src: block.src,\n ...(block.alt && { alt: block.alt }),\n ...(block.width !== undefined && { width: block.width }),\n ...(block.height !== undefined && { height: block.height }),\n }\n case 'file':\n return {\n type: 'file',\n url: block.url,\n name: block.name,\n ...(block.size !== undefined && { size: block.size }),\n ...(block.mimeType && { mimeType: block.mimeType }),\n }\n case 'break':\n return { type: 'break' }\n case 'custom':\n return {\n type: 'custom',\n kind: block.kind,\n data: cloneRecord(block.data),\n ...(block.fallback && { fallback: block.fallback }),\n }\n }\n}\n\nfunction normalizeContentBlock(value: unknown): ChatContentBlock | null {\n if (!isRecord(value) || typeof value.type !== 'string') return null\n switch (value.type) {\n case 'text':\n return typeof value.text === 'string'\n ? { type: 'text', text: value.text }\n : null\n case 'mention':\n return typeof value.id === 'string' && typeof value.label === 'string'\n ? { type: 'mention', id: value.id, label: value.label }\n : null\n case 'link':\n return typeof value.url === 'string'\n ? {\n type: 'link',\n url: value.url,\n ...(typeof value.label === 'string' && { label: value.label }),\n }\n : null\n case 'code':\n return typeof value.code === 'string'\n ? {\n type: 'code',\n code: value.code,\n ...(typeof value.language === 'string' && {\n language: value.language,\n }),\n }\n : null\n case 'image':\n return typeof value.src === 'string'\n ? {\n type: 'image',\n src: value.src,\n ...(typeof value.alt === 'string' && { alt: value.alt }),\n ...(isPositiveNumber(value.width) && { width: value.width }),\n ...(isPositiveNumber(value.height) && { height: value.height }),\n }\n : null\n case 'file':\n return typeof value.url === 'string' && typeof value.name === 'string'\n ? {\n type: 'file',\n url: value.url,\n name: value.name,\n ...(isPositiveNumber(value.size) && { size: value.size }),\n ...(typeof value.mimeType === 'string' && {\n mimeType: value.mimeType,\n }),\n }\n : null\n case 'break':\n return { type: 'break' }\n case 'custom':\n return typeof value.kind === 'string' && isRecord(value.data)\n ? {\n type: 'custom',\n kind: value.kind,\n data: cloneRecord(value.data),\n ...(typeof value.fallback === 'string' && {\n fallback: value.fallback,\n }),\n }\n : fallbackBlock(value)\n default:\n return fallbackBlock(value)\n }\n}\n\nfunction fallbackBlock(\n value: Record<string, unknown>\n): ChatContentBlock | null {\n return typeof value.fallback === 'string'\n ? { type: 'text', text: value.fallback }\n : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isPositiveNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0\n}\n\nfunction cloneUser(user: ChatUser): ChatUser {\n return { ...user }\n}\n\nfunction cloneMention(mention: MentionItem): MentionItem {\n return { ...mention }\n}\n\nfunction cloneImage(image: ImageAttachment): ImageAttachment {\n return { ...image }\n}\n\nfunction cloneFile(file: FileAttachment): FileAttachment {\n return { ...file }\n}\n\nfunction cloneRecord<T>(value: T, seen = new WeakMap<object, unknown>()): T {\n if (!value || typeof value !== 'object') return value\n if (seen.has(value)) return seen.get(value) as T\n if (Array.isArray(value)) {\n const clone: unknown[] = []\n seen.set(value, clone)\n value.forEach(item => clone.push(cloneRecord(item, seen)))\n return clone as T\n }\n\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) return value\n const clone: Record<string, unknown> = {}\n seen.set(value, clone)\n Object.entries(value).forEach(([key, item]) => {\n clone[key] = cloneRecord(item, seen)\n })\n return clone as T\n}\n","import type { ChatMessage, MessageStatus } from '../types'\nimport type { EventEmitter } from './event-emitter'\nimport {\n cloneChatMessage,\n normalizeChatMessage,\n normalizeChatMessages,\n} from './message-schema'\n\nexport type MessageMergeResult = 'added' | 'updated' | 'ignored'\n\nexport interface MessageMergeOptions {\n sequence?: number\n source?: 'local' | 'remote'\n}\n\nexport interface StreamAppendOptions {\n generation?: string\n sequence?: number\n}\n\ninterface StreamState {\n generation: string\n lastSequence: number\n}\n\n/** ChatManager - 聊天消息状态、幂等合并和流式 generation 管理。 */\nexport class ChatManager {\n private messages: ChatMessage[] = []\n private readonly emitter: EventEmitter\n private readonly streams = new Map<string, StreamState>()\n\n constructor(emitter: EventEmitter, initialMessages?: ChatMessage[]) {\n this.emitter = emitter\n if (initialMessages?.length) {\n this.messages = normalizeChatMessages(initialMessages)\n }\n }\n\n getMessages(): ChatMessage[] {\n return this.messages.map(cloneChatMessage)\n }\n\n getMessage(id: string): ChatMessage | undefined {\n const message = this.messages.find(item => item.id === id)\n return message ? cloneChatMessage(message) : undefined\n }\n\n getMessageIdByClientMessageId(clientMessageId: string): string | undefined {\n return this.messages.find(\n message => message.clientMessageId === clientMessageId\n )?.id\n }\n\n addMessage(message: ChatMessage): void {\n const storedMessage = normalizeChatMessage(message)\n this.assertUniqueIds([storedMessage])\n this.messages.push(storedMessage)\n this.emitAdded(storedMessage)\n }\n\n prependMessages(messages: ChatMessage[]): void {\n const storedMessages = normalizeChatMessages(messages)\n this.assertUniqueIds(storedMessages)\n this.messages.unshift(...storedMessages)\n this.emitter.emit(\n 'messages-prepended',\n storedMessages.map(cloneChatMessage)\n )\n this.emitChanged()\n }\n\n /** 合并本地 ack 或远端推送,按 id/clientMessageId 去重并拒绝旧 sequence。 */\n upsertMessage(\n message: ChatMessage,\n options: MessageMergeOptions = {}\n ): MessageMergeResult {\n const normalized = normalizeChatMessage({\n ...message,\n ...(options.sequence !== undefined && { sequence: options.sequence }),\n })\n const index = this.findMessageIndex(normalized)\n\n if (index < 0) {\n this.messages.push(normalized)\n this.emitAdded(normalized)\n return 'added'\n }\n\n const current = this.messages[index]\n if (\n Number.isFinite(normalized.sequence) &&\n Number.isFinite(current.sequence) &&\n (normalized.sequence as number) <= (current.sequence as number)\n ) {\n return 'ignored'\n }\n\n const merged = normalizeChatMessage({\n ...current,\n ...normalized,\n id: current.id,\n clientMessageId: normalized.clientMessageId ?? current.clientMessageId,\n sequence: normalized.sequence ?? current.sequence,\n })\n this.messages[index] = merged\n this.emitter.emit('message-updated', cloneChatMessage(merged))\n this.emitChanged()\n return 'updated'\n }\n\n mergeMessages(\n messages: ChatMessage[],\n options: MessageMergeOptions = {}\n ): { added: number; updated: number; ignored: number } {\n const result = { added: 0, updated: 0, ignored: 0 }\n for (const message of messages) {\n const outcome = this.upsertMessage(message, options)\n result[outcome] += 1\n }\n return result\n }\n\n updateMessage(id: string, updates: Partial<ChatMessage>): void {\n const index = this.messages.findIndex(message => message.id === id)\n if (index === -1) return\n if (updates.id !== undefined && updates.id !== id) {\n throw new Error('Chat message IDs are immutable.')\n }\n\n const next = normalizeChatMessage({\n ...this.messages[index],\n ...updates,\n id,\n })\n this.assertUniqueClientMessageId(next, id)\n this.messages[index] = next\n this.emitter.emit('message-updated', cloneChatMessage(next))\n this.emitChanged()\n }\n\n markMessageStatus(id: string, status: MessageStatus): void {\n this.updateMessage(id, { status })\n }\n\n removeMessage(id: string): void {\n const index = this.messages.findIndex(message => message.id === id)\n if (index === -1) return\n\n const [removed] = this.messages.splice(index, 1)\n this.streams.delete(id)\n this.emitter.emit('message-removed', cloneChatMessage(removed))\n this.emitChanged()\n }\n\n setMessages(messages: ChatMessage[]): void {\n this.messages = normalizeChatMessages(messages)\n this.streams.clear()\n this.emitChanged()\n }\n\n clearMessages(): void {\n this.messages = []\n this.streams.clear()\n this.emitChanged()\n }\n\n beginStreaming(id: string, generation = createGeneration()): string | null {\n const index = this.messages.findIndex(message => message.id === id)\n if (index === -1) return null\n this.streams.set(id, { generation, lastSequence: -1 })\n this.messages[index] = normalizeChatMessage({\n ...this.messages[index],\n streaming: true,\n })\n this.emitter.emit('message-updated', cloneChatMessage(this.messages[index]))\n this.emitChanged()\n return generation\n }\n\n appendMessageContent(\n id: string,\n chunk: string,\n options: StreamAppendOptions = {}\n ): boolean {\n const stream = this.streams.get(id)\n if (options.generation) {\n if (!stream || stream.generation !== options.generation) return false\n const sequence = options.sequence\n if (\n sequence !== undefined &&\n Number.isFinite(sequence) &&\n sequence <= stream.lastSequence\n ) {\n return false\n }\n if (sequence !== undefined && Number.isFinite(sequence)) {\n stream.lastSequence = sequence\n }\n }\n\n const index = this.messages.findIndex(message => message.id === id)\n if (index === -1) return false\n const message = this.messages[index]\n this.messages[index] = normalizeChatMessage({\n ...message,\n content: (message.content ?? '') + chunk,\n streaming: options.generation ? true : message.streaming,\n })\n this.emitter.emit(\n 'message-content-appended',\n id,\n this.messages[index].content,\n options.generation,\n options.sequence\n )\n this.emitChanged()\n return true\n }\n\n finishStreaming(id: string, generation?: string): boolean {\n const stream = this.streams.get(id)\n if (generation && (!stream || stream.generation !== generation)) {\n return false\n }\n const index = this.messages.findIndex(message => message.id === id)\n if (index === -1) return false\n this.messages[index] = normalizeChatMessage({\n ...this.messages[index],\n streaming: false,\n })\n this.streams.delete(id)\n this.emitter.emit('message-updated', cloneChatMessage(this.messages[index]))\n this.emitChanged()\n return true\n }\n\n cancelStreaming(id: string, generation?: string): boolean {\n const stream = this.streams.get(id)\n if (generation && (!stream || stream.generation !== generation)) {\n return false\n }\n const index = this.messages.findIndex(message => message.id === id)\n if (index === -1) return false\n this.streams.delete(id)\n this.messages[index] = normalizeChatMessage({\n ...this.messages[index],\n streaming: false,\n })\n this.emitter.emit(\n 'stream-cancelled',\n cloneChatMessage(this.messages[index])\n )\n this.emitter.emit('message-updated', cloneChatMessage(this.messages[index]))\n this.emitChanged()\n return true\n }\n\n getStreamGeneration(id: string): string | undefined {\n return this.streams.get(id)?.generation\n }\n\n private findMessageIndex(message: ChatMessage): number {\n const byId = this.messages.findIndex(item => item.id === message.id)\n if (byId >= 0) return byId\n if (!message.clientMessageId) return -1\n return this.messages.findIndex(\n item => item.clientMessageId === message.clientMessageId\n )\n }\n\n private assertUniqueIds(messages: ChatMessage[]): void {\n const ids = new Set(this.messages.map(message => message.id))\n const clientIds = new Set(\n this.messages.flatMap(message =>\n message.clientMessageId ? [message.clientMessageId] : []\n )\n )\n for (const message of messages) {\n if (!message.id || ids.has(message.id)) {\n throw new Error(\n `Chat message ID must be non-empty and unique: ${message.id}`\n )\n }\n if (message.clientMessageId && clientIds.has(message.clientMessageId)) {\n throw new Error(\n `Chat client message ID must be unique: ${message.clientMessageId}`\n )\n }\n ids.add(message.id)\n if (message.clientMessageId) clientIds.add(message.clientMessageId)\n }\n }\n\n private assertUniqueClientMessageId(message: ChatMessage, ownId: string) {\n if (\n message.clientMessageId &&\n this.messages.some(\n item =>\n item.id !== ownId && item.clientMessageId === message.clientMessageId\n )\n ) {\n throw new Error(\n `Chat client message ID must be unique: ${message.clientMessageId}`\n )\n }\n }\n\n private emitAdded(message: ChatMessage): void {\n this.emitter.emit('message-added', cloneChatMessage(message))\n this.emitChanged()\n }\n\n private emitChanged(): void {\n this.emitter.emit('messages-changed', this.getMessages())\n }\n}\n\nfunction createGeneration(): string {\n const cryptoObject = globalThis.crypto\n if (cryptoObject?.randomUUID) return cryptoObject.randomUUID()\n return `stream-${Date.now()}-${Math.random().toString(36).slice(2)}`\n}\n","/**\r\n * 轻量事件总线\r\n * 提供发布/订阅模式的事件管理功能,支持事件的注册、注销、触发等操作\r\n */\r\n\r\n// 定义事件处理函数的类型签名:接收任意数量的未知类型参数,无返回值\r\ntype Handler = (...args: unknown[]) => void\r\n\r\n/**\r\n * EventEmitter - 事件发射器类\r\n * 实现了经典的发布/订阅(Pub/Sub)模式,用于模块间的解耦通信\r\n * 支持:一次性监听、批量移除、自动清理等功能\r\n */\r\nexport class EventEmitter {\r\n // 使用 Map 存储事件名到处理函数集合的映射关系\r\n // 键为事件名称(字符串),值为该事件对应的处理函数 Set 集合\r\n // 使用 Set 而非数组,可自动去重同一处理函数的重复注册\r\n private listeners = new Map<string, Set<Handler>>()\r\n\r\n /**\r\n * 注册事件监听器\r\n * @param event - 要监听的事件名称\r\n * @param handler - 事件触发时执行的回调函数\r\n * @returns 返回一个取消订阅的函数,调用即可移除该监听器\r\n */\r\n on(event: string, handler: Handler): () => void {\r\n let handlers = this.listeners.get(event)\r\n if (!handlers) {\r\n handlers = new Set()\r\n this.listeners.set(event, handlers)\r\n }\r\n handlers.add(handler)\r\n // 返回一个取消订阅函数,方便调用者链式调用后自行移除\r\n return () => this.off(event, handler)\r\n }\r\n\r\n /**\r\n * 移除指定事件的某个监听器\r\n * @param event - 事件名称\r\n * @param handler - 要移除的处理函数引用(必须与注册时为同一函数引用)\r\n */\r\n off(event: string, handler: Handler): void {\r\n // 可选链调用:如果该事件存在监听器集合,则从中删除指定处理函数\r\n // 若事件不存在则安全跳过,不会抛出异常\r\n const handlers = this.listeners.get(event)\r\n if (!handlers) return\r\n handlers.delete(handler)\r\n if (handlers.size === 0) this.listeners.delete(event)\r\n }\r\n\r\n /**\r\n * 触发(发射)指定事件,依次调用所有已注册的监听器\r\n * @param event - 要触发的事件名称\r\n * @param args - 传递给监听器函数的参数列表(剩余参数语法)\r\n */\r\n emit(event: string, ...args: unknown[]): void {\r\n // 获取该事件的监听器集合,若存在则遍历调用每个处理函数\r\n ;[...(this.listeners.get(event) ?? [])].forEach(handler => {\r\n try {\r\n // 使用展开运算符将参数数组传递给处理函数\r\n handler(...args)\r\n } catch (err) {\r\n // 捕获单个处理函数的异常,避免影响其他监听器的执行\r\n // 同时输出错误日志便于调试,标注所属模块为 [Chat]\r\n console.error(`[Chat] Event handler error for \"${event}\":`, err)\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * 注册一次性事件监听器(触发一次后自动移除)\r\n * @param event - 要监听的事件名称\r\n * @param handler - 事件触发时执行的回调函数\r\n * @returns 返回取消订阅的函数,可在触发前手动取消\r\n */\r\n once(event: string, handler: Handler): () => void {\r\n // 创建包装函数:先移除自身,再调用原始处理函数\r\n // 这样保证该监听器只执行一次\r\n const wrapper = (...args: unknown[]) => {\r\n // 先从事件中移除包装函数自身,防止重复触发\r\n this.off(event, wrapper)\r\n // 再执行用户注册的原始处理函数\r\n handler(...args)\r\n }\r\n // 将包装函数注册为普通监听器,复用 on() 的逻辑\r\n return this.on(event, wrapper)\r\n }\r\n\r\n /**\r\n * 批量移除事件监听器\r\n * @param event - 可选的事件名称\r\n * - 若传入事件名,则只移除该事件的所有监听器\r\n * - 若不传参数,则清空所有事件的所有监听器\r\n */\r\n removeAll(event?: string): void {\r\n if (event !== undefined) {\r\n // 移除指定事件的全部监听器(直接删除整个事件条目)\r\n this.listeners.delete(event)\r\n } else {\r\n // 不传参数时,清空整个监听器映射表,移除所有事件\r\n this.listeners.clear()\r\n }\r\n }\r\n}\r\n","/**\r\n * @file mention-engine.ts\r\n * @description mention-engine 模块\r\n */\r\n\r\nimport type { MentionItem } from '../types'\r\nimport type { EventEmitter } from './event-emitter'\r\n\r\n/**\r\n * MentionState interface\r\n */\r\nexport interface MentionState {\r\n active: boolean\r\n query: string\r\n filtered: MentionItem[]\r\n activeIndex: number\r\n triggerPosition: number\r\n}\r\n\r\n/**\r\n * MentionEngine 类\r\n */\r\nexport class MentionEngine {\r\n private members: MentionItem[] = []\r\n private emitter: EventEmitter\r\n private state: MentionState = {\r\n active: false,\r\n query: '',\r\n filtered: [],\r\n activeIndex: 0,\r\n triggerPosition: -1,\r\n }\r\n private selectedMentions: MentionItem[] = []\r\n\r\n constructor(emitter: EventEmitter, members?: MentionItem[]) {\r\n this.emitter = emitter\r\n if (members) this.members = members.map(member => ({ ...member }))\r\n }\r\n\r\n getState(): MentionState {\r\n return {\r\n ...this.state,\r\n filtered: [...this.state.filtered],\r\n }\r\n }\r\n\r\n getSelectedMentions(): MentionItem[] {\r\n return this.selectedMentions.map(member => ({ ...member }))\r\n }\r\n\r\n setMembers(members: MentionItem[]): void {\r\n this.members = members.map(member => ({ ...member }))\r\n if (this.state.active) {\r\n this.filter(this.state.query)\r\n }\r\n }\r\n\r\n handleInput(text: string, cursorPos: number): void {\r\n const beforeCursor = text.slice(0, cursorPos)\r\n const atIndex = beforeCursor.lastIndexOf('@')\r\n\r\n if (atIndex === -1) {\r\n this.deactivate()\r\n return\r\n }\r\n\r\n if (atIndex > 0 && !/\\s/.test(beforeCursor[atIndex - 1])) {\r\n this.deactivate()\r\n return\r\n }\r\n\r\n const query = beforeCursor.slice(atIndex + 1)\r\n if (/\\s/.test(query)) {\r\n this.deactivate()\r\n return\r\n }\r\n\r\n this.state.active = true\r\n this.state.triggerPosition = atIndex\r\n this.filter(query)\r\n }\r\n\r\n moveUp(): void {\r\n if (!this.state.active || this.state.filtered.length === 0) return\r\n this.state.activeIndex =\r\n (this.state.activeIndex - 1 + this.state.filtered.length) %\r\n this.state.filtered.length\r\n this.emitter.emit('mention-active-change', this.state.activeIndex)\r\n }\r\n\r\n moveDown(): void {\r\n if (!this.state.active || this.state.filtered.length === 0) return\r\n this.state.activeIndex =\r\n (this.state.activeIndex + 1) % this.state.filtered.length\r\n this.emitter.emit('mention-active-change', this.state.activeIndex)\r\n }\r\n\r\n selectCurrent(): MentionItem | null {\r\n if (!this.state.active || this.state.filtered.length === 0) return null\r\n return this.select(this.state.activeIndex)\r\n }\r\n\r\n select(index: number): MentionItem | null {\r\n if (index < 0 || index >= this.state.filtered.length) return null\r\n const member = this.state.filtered[index]\r\n if (!this.selectedMentions.some(m => m.id === member.id)) {\r\n this.selectedMentions.push(member)\r\n }\r\n this.emitter.emit('mention-select', member)\r\n this.deactivate()\r\n return member\r\n }\r\n\r\n deactivate(): void {\r\n if (!this.state.active) return\r\n this.state = {\r\n active: false,\r\n query: '',\r\n filtered: [],\r\n activeIndex: 0,\r\n triggerPosition: -1,\r\n }\r\n this.emitter.emit('mention-deactivate')\r\n }\r\n\r\n parseMentions(text: string): MentionItem[] {\r\n const mentions: MentionItem[] = []\r\n const sortedMembers = [...this.members].sort(\r\n (a, b) => b.name.length - a.name.length\r\n )\r\n\r\n for (const member of sortedMembers) {\r\n const pattern = new RegExp(\r\n `(^|\\\\s)@${this.escapeRegex(member.name)}(?=\\\\s|$|[,。!?,.!?])`,\r\n 'u'\r\n )\r\n if (pattern.test(text) && !mentions.some(m => m.id === member.id)) {\r\n mentions.push({ ...member })\r\n }\r\n }\r\n\r\n return mentions\r\n }\r\n\r\n resetSelected(): void {\r\n this.selectedMentions = []\r\n }\r\n\r\n getInsertText(member: MentionItem): string {\r\n return `@${member.name} `\r\n }\r\n\r\n private filter(query: string): void {\r\n const normalizedQuery = query.trim().toLowerCase()\r\n this.state.query = query\r\n this.state.filtered = this.members\r\n .filter(\r\n member =>\r\n member.name.toLowerCase().includes(normalizedQuery) ||\r\n member.id.toLowerCase().includes(normalizedQuery)\r\n )\r\n .map(member => ({ ...member }))\r\n this.state.activeIndex = 0\r\n this.emitter.emit('mention-filter', this.getState())\r\n }\r\n\r\n private escapeRegex(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\r\n }\r\n}\r\n","import type { ChatMessage } from '../types'\n\n/** transport 连接状态。 */\nexport type ChatTransportStatus =\n 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error'\n\n/** 建立 transport 时传入的同步上下文。 */\nexport interface ChatTransportContext {\n conversationId?: string\n cursor?: string\n signal?: AbortSignal\n}\n\n/** transport ack,可携带服务端补全后的消息和同步序号。 */\nexport interface ChatTransportAck {\n clientMessageId: string\n message?: Partial<ChatMessage>\n sequence?: number\n cursor?: string\n}\n\n/** transport 推送的统一事件协议。 */\nexport type ChatTransportEvent =\n | {\n type: 'message'\n message: ChatMessage\n sequence?: number\n cursor?: string\n }\n | { type: 'ack'; ack: ChatTransportAck }\n | { type: 'cursor'; cursor: string }\n | { type: 'error'; error: unknown; recoverable?: boolean }\n\n/** 可由 HTTP/SSE/WebSocket/原生 App bridge 实现的最小 transport 协议。 */\nexport interface ChatTransport {\n connect: (context?: ChatTransportContext) => void | Promise<void>\n disconnect: () => void | Promise<void>\n send: (\n message: ChatMessage,\n options?: { signal?: AbortSignal; clientMessageId?: string }\n ) => Promise<ChatTransportAck | void>\n subscribe: (listener: (event: ChatTransportEvent) => void) => () => void\n onStatusChange?: (\n listener: (status: ChatTransportStatus) => void\n ) => () => void\n}\n\nexport interface ChatTransportControllerOptions {\n conversationId?: string\n cursor?: string\n onEvent?: (event: ChatTransportEvent) => void\n onStatusChange?: (status: ChatTransportStatus) => void\n}\n\n/**\n * 连接生命周期、游标和外部 transport 事件的统一控制器。\n *\n * Controller 不假设网络实现,负责避免重复 connect、转发状态、保存 cursor,\n * 并在 dispose 后拒绝迟到的异步结果。\n */\nexport class ChatTransportController {\n private readonly transport: ChatTransport\n private readonly options: ChatTransportControllerOptions\n private status: ChatTransportStatus = 'idle'\n private cursor?: string\n private unsubscribeEvents: (() => void) | null = null\n private unsubscribeStatus: (() => void) | null = null\n private destroyed = false\n private connectPromise: Promise<void> | null = null\n private lifecycle = 0\n\n constructor(\n transport: ChatTransport,\n options: ChatTransportControllerOptions = {}\n ) {\n this.transport = transport\n this.options = options\n this.cursor = options.cursor\n }\n\n getStatus(): ChatTransportStatus {\n return this.status\n }\n\n getCursor(): string | undefined {\n return this.cursor\n }\n\n async connect(signal?: AbortSignal): Promise<void> {\n if (this.destroyed)\n throw new Error('Chat transport controller is disposed.')\n if (this.status === 'connected') return\n if (this.connectPromise) return this.connectPromise\n\n const lifecycle = ++this.lifecycle\n this.setStatus('connecting')\n this.connectPromise = (async () => {\n this.unsubscribeEvents?.()\n this.unsubscribeStatus?.()\n this.unsubscribeEvents = this.transport.subscribe(event =>\n this.handleEvent(event)\n )\n this.unsubscribeStatus =\n this.transport.onStatusChange?.(status => this.setStatus(status)) ??\n null\n try {\n await this.transport.connect({\n conversationId: this.options.conversationId,\n cursor: this.cursor,\n signal,\n })\n if (this.destroyed || lifecycle !== this.lifecycle) return\n this.setStatus('connected')\n } catch (error) {\n if (!this.destroyed && lifecycle === this.lifecycle) {\n this.setStatus('error')\n }\n throw error\n } finally {\n this.connectPromise = null\n }\n })()\n\n return this.connectPromise\n }\n\n async disconnect(): Promise<void> {\n if (this.destroyed) return\n this.lifecycle += 1\n this.connectPromise = null\n try {\n await this.transport.disconnect()\n } finally {\n this.setStatus('disconnected')\n }\n }\n\n async send(\n message: ChatMessage,\n options: { signal?: AbortSignal; clientMessageId?: string } = {}\n ): Promise<ChatTransportAck | void> {\n if (this.destroyed)\n throw new Error('Chat transport controller is disposed.')\n if (this.status !== 'connected') {\n throw new Error(`Chat transport is not connected: ${this.status}`)\n }\n const result = await this.transport.send(message, options)\n if (result && result.cursor) this.cursor = result.cursor\n return result\n }\n\n dispose(): void {\n if (this.destroyed) return\n this.destroyed = true\n this.lifecycle += 1\n this.unsubscribeEvents?.()\n this.unsubscribeStatus?.()\n this.unsubscribeEvents = null\n this.unsubscribeStatus = null\n this.connectPromise = null\n void Promise.resolve(this.transport.disconnect()).catch(() => undefined)\n this.setStatus('disconnected')\n }\n\n private handleEvent(event: ChatTransportEvent): void {\n if (this.destroyed) return\n if ('cursor' in event && event.cursor) this.cursor = event.cursor\n if (event.type === 'ack' && event.ack.cursor) {\n this.cursor = event.ack.cursor\n }\n if (event.type === 'error' && !event.recoverable) this.setStatus('error')\n this.options.onEvent?.(event)\n }\n\n private setStatus(status: ChatTransportStatus): void {\n if (this.status === status) return\n this.status = status\n this.options.onStatusChange?.(status)\n }\n}\n","/**\r\n * @file style-manager.ts\r\n * @description style-manager 模块\r\n */\r\n\r\nimport type { ThemeTokens } from '../theme/tokens'\r\nimport {\r\n COMPONENT_CSS_VAR_PREFIX,\r\n cx,\r\n DEFAULT_CLASS_PREFIX,\r\n getStyleElementId,\r\n normalizeClassPrefix,\r\n} from '../constants/dom'\r\n\r\nconst styleRefs = new WeakMap<Document, Map<string, number>>()\r\n\r\n/**\r\n * injectStyles - inject Styles function\r\n * @param tokens - Theme token values\r\n * @param prefix - CSS class prefix\r\n * @param targetRoot - Optional root that receives theme variables\r\n */\r\nexport function injectStyles(\r\n tokens: ThemeTokens,\r\n prefix: string = DEFAULT_CLASS_PREFIX,\r\n targetRoot?: HTMLElement\r\n): void {\r\n const normalizedPrefix = normalizeClassPrefix(prefix)\r\n const styleId = getStyleElementId(normalizedPrefix)\r\n const ownerDocument = resolveDocument(targetRoot?.ownerDocument)\r\n const refs = getDocumentRefs(ownerDocument)\r\n refs.set(styleId, (refs.get(styleId) ?? 0) + 1)\r\n if (!ownerDocument.getElementById(styleId)) {\r\n upsertStyle(ownerDocument, styleId, generateCSS(tokens, normalizedPrefix))\r\n }\r\n if (targetRoot) applyThemeTokens(targetRoot, tokens)\r\n}\r\n\r\n/**\r\n * updateStyles - update Styles function\r\n * @param tokens - Theme token values\r\n * @param prefix - CSS class prefix\r\n * @param targetRoot - Optional root that receives theme variables\r\n */\r\nexport function updateStyles(\r\n tokens: ThemeTokens,\r\n prefix: string = DEFAULT_CLASS_PREFIX,\r\n targetRoot?: HTMLElement\r\n): void {\r\n const normalizedPrefix = normalizeClassPrefix(prefix)\r\n const styleId = getStyleElementId(normalizedPrefix)\r\n if (targetRoot) {\r\n applyThemeTokens(targetRoot, tokens)\r\n } else {\r\n const ownerDocument = resolveDocument()\r\n upsertStyle(ownerDocument, styleId, generateCSS(tokens, normalizedPrefix))\r\n }\r\n}\r\n\r\n/**\r\n * removeStyles - remove Styles function\r\n * @param prefix - CSS class prefix\r\n * @param ownerDocument - Document that owns the injected stylesheet\r\n */\r\nexport function removeStyles(\r\n prefix: string = DEFAULT_CLASS_PREFIX,\r\n ownerDocument?: Document\r\n): void {\r\n const doc = resolveDocument(ownerDocument)\r\n const refsByStyle = getDocumentRefs(doc)\r\n const styleId = getStyleElementId(prefix)\r\n const refs = refsByStyle.get(styleId) ?? 0\r\n if (refs > 1) {\r\n refsByStyle.set(styleId, refs - 1)\r\n return\r\n }\r\n\r\n refsByStyle.delete(styleId)\r\n doc.getElementById(styleId)?.remove()\r\n}\r\n\r\n/**\r\n * cls - cls function\r\n * @param prefix - CSS class prefix\r\n * @param parts - Class name parts\r\n */\r\nexport function cls(prefix: string, ...parts: string[]): string {\r\n const normalizedPrefix = normalizeClassPrefix(prefix)\r\n return parts.map(part => `${normalizedPrefix}-${part}`).join(' ')\r\n}\r\n\r\nexport const clsx = cx\r\n\r\nfunction upsertStyle(\r\n ownerDocument: Document,\r\n styleId: string,\r\n cssText: string\r\n): void {\r\n let style = ownerDocument.getElementById(styleId) as HTMLStyleElement | null\r\n if (!style) {\r\n style = ownerDocument.createElement('style')\r\n style.id = styleId\r\n style.dataset.ldesignChat = 'true'\r\n ;(ownerDocument.head ?? ownerDocument.documentElement).appendChild(style)\r\n }\r\n style.textContent = cssText\r\n}\r\n\r\nexport function applyThemeTokens(root: HTMLElement, tokens: ThemeTokens): void {\r\n Object.entries(themeVariableMap(tokens)).forEach(([name, value]) => {\r\n root.style.setProperty(name, value)\r\n })\r\n}\r\n\r\nfunction resolveDocument(ownerDocument?: Document): Document {\r\n if (ownerDocument) return ownerDocument\r\n if (typeof document !== 'undefined') return document\r\n throw new Error('[Chat] Styles require a browser Document.')\r\n}\r\n\r\nfunction getDocumentRefs(ownerDocument: Document): Map<string, number> {\r\n let refs = styleRefs.get(ownerDocument)\r\n if (!refs) {\r\n refs = new Map()\r\n styleRefs.set(ownerDocument, refs)\r\n }\r\n return refs\r\n}\r\n\r\nfunction tokenVars(t: ThemeTokens): string {\r\n return Object.entries(themeVariableMap(t))\r\n .map(([key, value]) => ` ${key}: ${value};`)\r\n .join('\\n')\r\n}\r\n\r\nfunction themeVariableMap(t: ThemeTokens): Record<string, string> {\r\n const vars: Record<string, string> = {\r\n bgPrimary: t.bgPrimary,\r\n bgSecondary: t.bgSecondary,\r\n bgBubbleOutgoing: t.bgBubbleOutgoing,\r\n bgBubbleIncoming: t.bgBubbleIncoming,\r\n bgInput: t.bgInput,\r\n bgMention: t.bgMention,\r\n bgMentionHover: t.bgMentionHover,\r\n bgMentionActive: t.bgMentionActive,\r\n bgLoadMore: t.bgLoadMore,\r\n bgSystemMessage: t.bgSystemMessage,\r\n bgDropOverlay: t.bgDropOverlay,\r\n bgDangerSoft: t.bgDangerSoft,\r\n textPrimary: t.textPrimary,\r\n textSecondary: t.textSecondary,\r\n textBubbleOutgoing: t.textBubbleOutgoing,\r\n textBubbleIncoming: t.textBubbleIncoming,\r\n textMention: t.textMention,\r\n textMentionTag: t.textMentionTag,\r\n textTimestamp: t.textTimestamp,\r\n textSystem: t.textSystem,\r\n textPlaceholder: t.textPlaceholder,\r\n borderPrimary: t.borderPrimary,\r\n borderInput: t.borderInput,\r\n borderInputFocus: t.borderInputFocus,\r\n borderMention: t.borderMention,\r\n colorSending: t.colorSending,\r\n colorSent: t.colorSent,\r\n colorDelivered: t.colorDelivered,\r\n colorRead: t.colorRead,\r\n colorFailed: t.colorFailed,\r\n colorLink: t.colorLink,\r\n shadowPanel: t.shadowPanel,\r\n shadowMention: t.shadowMention,\r\n avatarBg: t.avatarBg,\r\n avatarText: t.avatarText,\r\n btnPrimaryBg: t.btnPrimaryBg,\r\n btnPrimaryText: t.btnPrimaryText,\r\n btnPrimaryHover: t.btnPrimaryHover,\r\n scrollbarThumb: t.scrollbarThumb,\r\n scrollbarTrack: t.scrollbarTrack,\r\n bgToolbar: t.bgToolbar,\r\n borderToolbar: t.borderToolbar,\r\n toolbarIconColor: t.toolbarIconColor,\r\n toolbarIconHover: t.toolbarIconHover,\r\n toolbarVoiceActive: t.toolbarVoiceActive,\r\n }\r\n\r\n return Object.fromEntries(\r\n Object.entries(vars).map(([key, value]) => [\r\n `${COMPONENT_CSS_VAR_PREFIX}-${toKebab(key)}`,\r\n value,\r\n ])\r\n )\r\n}\r\n\r\nfunction sizeVars(): string {\r\n return `\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-family: var(--ld-font-family);\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-size: var(--ld-font-base);\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-size-sm: var(--ld-font-sm);\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-size-xs: var(--ld-font-xs);\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-size-lg: var(--ld-font-lg);\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-weight-regular: 400;\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-weight-medium: 500;\r\n ${COMPONENT_CSS_VAR_PREFIX}-font-weight-semibold: 600;\r\n ${COMPONENT_CSS_VAR_PREFIX}-line-height: var(--ld-line-normal);\r\n ${COMPONENT_CSS_VAR_PREFIX}-line-height-bubble: 1.6;\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-1: var(--ld-spacing-3xs);\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-2: var(--ld-spacing-2xs);\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-3: var(--ld-spacing-xs);\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-4: var(--ld-spacing-sm);\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-5: var(--ld-spacing-md);\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-6: var(--ld-spacing-lg);\r\n ${COMPONENT_CSS_VAR_PREFIX}-space-8: var(--ld-spacing-xl);\r\n ${COMPONENT_CSS_VAR_PREFIX}-avatar-size: calc(var(--ld-px-40) + var(--ld-px-4));\r\n ${COMPONENT_CSS_VAR_PREFIX}-mention-avatar-size: var(--ld-px-36);\r\n ${COMPONENT_CSS_VAR_PREFIX}-toolbar-button-size: var(--ld-px-36);\r\n ${COMPONENT_CSS_VAR_PREFIX}-input-button-size: calc(var(--ld-px-40) + var(--ld-px-4));\r\n ${COMPONENT_CSS_VAR_PREFIX}-file-icon-size: var(--ld-px-48);\r\n ${COMPONENT_CSS_VAR_PREFIX}-image-max-size: var(--ld-px-260);\r\n ${COMPONENT_CSS_VAR_PREFIX}-panel-max-height: var(--ld-px-220);\r\n ${COMPONENT_CSS_VAR_PREFIX}-textarea-min-height: calc(var(--ld-px-40) + var(--ld-px-4));\r\n ${COMPONENT_CSS_VAR_PREFIX}-textarea-max-height: calc(var(--ld-px-64) + var(--ld-px-56));\r\n ${COMPONENT_CSS_VAR_PREFIX}-message-max-width: 65%;\r\n ${COMPONENT_CSS_VAR_PREFIX}-system-message-max-width: 80%;\r\n ${COMPONENT_CSS_VAR_PREFIX}-file-bubble-min-width: var(--ld-px-220);\r\n ${COMPONENT_CSS_VAR_PREFIX}-border-width: var(--ld-border-width-thin);\r\n ${COMPONENT_CSS_VAR_PREFIX}-border-width-drop: var(--ld-border-width-medium);\r\n ${COMPONENT_CSS_VAR_PREFIX}-radius-xs: var(--ld-radius-sm);\r\n ${COMPONENT_CSS_VAR_PREFIX}-radius-sm: var(--ld-radius-md);\r\n ${COMPONENT_CSS_VAR_PREFIX}-radius-md: var(--ld-radius-lg);\r\n ${COMPONENT_CSS_VAR_PREFIX}-radius-lg: var(--ld-radius-xl);\r\n ${COMPONENT_CSS_VAR_PREFIX}-radius-pill: var(--ld-radius-full);\r\n ${COMPONENT_CSS_VAR_PREFIX}-radius-circle: var(--ld-radius-full);\r\n ${COMPONENT_CSS_VAR_PREFIX}-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);\r\n ${COMPONENT_CSS_VAR_PREFIX}-transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);\r\n ${COMPONENT_CSS_VAR_PREFIX}-z-overlay: 1000;\r\n ${COMPONENT_CSS_VAR_PREFIX}-z-mention: 1100;\r\n ${COMPONENT_CSS_VAR_PREFIX}-icon-size: var(--ld-px-24);\r\n`\r\n}\r\n\r\nfunction generateCSS(tokens: ThemeTokens, p: string): string {\r\n return `\r\n/* @composy/chat-core styles */\r\n.${p}-container,\r\n.${p}-container * {\r\n box-sizing: border-box;\r\n}\r\n\r\n.${p}-container {\r\n${tokenVars(tokens)}\r\n${sizeVars()}\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n overflow: hidden;\r\n position: relative;\r\n background: ${v('bg-primary')};\r\n color: ${v('text-primary')};\r\n font-family: ${v('font-family')};\r\n font-size: ${v('font-size')};\r\n line-height: ${v('line-height')};\r\n border: ${v('border-width')} solid ${v('border-primary')};\r\n border-radius: ${v('radius-md')};\r\n box-shadow: ${v('shadow-panel')};\r\n}\r\n\r\n.${p}-message-list {\r\n flex: 1;\r\n min-width: 0;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n padding: ${v('space-6')};\r\n scroll-behavior: smooth;\r\n}\r\n\r\n.${p}-message-list::-webkit-scrollbar {\r\n width: var(--ld-px-4);\r\n}\r\n\r\n.${p}-message-list::-webkit-scrollbar-thumb {\r\n background: ${v('scrollbar-thumb')};\r\n border-radius: ${v('radius-pill')};\r\n}\r\n\r\n.${p}-message-list::-webkit-scrollbar-track {\r\n background: ${v('scrollbar-track')};\r\n}\r\n\r\n.${p}-load-more {\r\n margin-bottom: ${v('space-5')};\r\n padding: ${v('space-5')};\r\n text-align: center;\r\n color: ${v('color-link')};\r\n font-size: ${v('font-size-sm')};\r\n background: ${v('bg-load-more')};\r\n border-radius: ${v('radius-sm')};\r\n cursor: pointer;\r\n user-select: none;\r\n transition: opacity ${v('transition-fast')}, background ${v('transition-fast')};\r\n}\r\n\r\n.${p}-load-more:hover {\r\n background: ${v('bg-mention-hover')};\r\n}\r\n\r\n.${p}-load-more--loading {\r\n cursor: default;\r\n opacity: .6;\r\n}\r\n\r\n.${p}-time-divider {\r\n padding: ${v('space-4')} 0;\r\n color: ${v('text-timestamp')};\r\n font-size: ${v('font-size-sm')};\r\n text-align: center;\r\n user-select: none;\r\n}\r\n\r\n.${p}-time-divider span {\r\n padding: ${v('space-1')} ${v('space-5')};\r\n background: ${v('bg-secondary')};\r\n border-radius: ${v('radius-pill')};\r\n}\r\n\r\n.${p}-message-row {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: ${v('space-4')};\r\n margin-bottom: ${v('space-5')};\r\n}\r\n\r\n.${p}-message-row--outgoing {\r\n flex-direction: row-reverse;\r\n}\r\n\r\n.${p}-message-row--system {\r\n justify-content: center;\r\n}\r\n\r\n.${p}-avatar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: ${v('avatar-size')};\r\n height: ${v('avatar-size')};\r\n overflow: hidden;\r\n flex-shrink: 0;\r\n color: ${v('avatar-text')};\r\n background: ${v('avatar-bg')};\r\n border-radius: ${v('radius-circle')};\r\n font-size: ${v('font-size')};\r\n font-weight: ${v('font-weight-semibold')};\r\n}\r\n\r\n.${p}-avatar img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n.${p}-message-body {\r\n display: flex;\r\n flex-direction: column;\r\n max-width: ${v('message-max-width')};\r\n min-width: 0;\r\n}\r\n\r\n.${p}-message-row--outgoing .${p}-message-body {\r\n align-items: flex-end;\r\n}\r\n\r\n.${p}-nickname {\r\n margin-bottom: ${v('space-2')};\r\n padding: 0 ${v('space-2')};\r\n color: ${v('text-secondary')};\r\n font-size: ${v('font-size-sm')};\r\n}\r\n\r\n.${p}-bubble {\r\n position: relative;\r\n max-width: 100%;\r\n padding: ${v('space-5')} ${v('space-6')};\r\n border-radius: ${v('radius-lg')};\r\n word-break: break-word;\r\n overflow-wrap: unknownwhere;\r\n white-space: pre-wrap;\r\n line-height: ${v('line-height-bubble')};\r\n}\r\n\r\n.${p}-bubble--incoming {\r\n color: ${v('text-bubble-incoming')};\r\n background: ${v('bg-bubble-incoming')};\r\n border-top-left-radius: ${v('radius-xs')};\r\n}\r\n\r\n.${p}-bubble--outgoing {\r\n color: ${v('text-bubble-outgoing')};\r\n background: ${v('bg-bubble-outgoing')};\r\n border-top-right-radius: ${v('radius-xs')};\r\n}\r\n\r\n.${p}-bubble--image {\r\n padding: ${v('space-2')};\r\n background: unset;\r\n}\r\n\r\n.${p}-bubble--image img {\r\n display: block;\r\n max-width: ${v('image-max-size')};\r\n max-height: ${v('image-max-size')};\r\n border-radius: ${v('radius-md')};\r\n cursor: pointer;\r\n}\r\n\r\n.${p}-bubble--file {\r\n display: flex;\r\n align-items: center;\r\n gap: ${v('space-5')};\r\n min-width: ${v('file-bubble-min-width')};\r\n}\r\n\r\n.${p}-file-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: ${v('file-icon-size')};\r\n height: ${v('file-icon-size')};\r\n flex-shrink: 0;\r\n background: ${v('bg-secondary')};\r\n border-radius: ${v('radius-sm')};\r\n font-size: ${v('font-size-lg')};\r\n}\r\n\r\n.${p}-file-info {\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.${p}-file-name {\r\n overflow: hidden;\r\n font-size: ${v('font-size')};\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.${p}-file-size {\r\n margin-top: ${v('space-1')};\r\n color: ${v('text-secondary')};\r\n font-size: ${v('font-size-sm')};\r\n}\r\n\r\n.${p}-system-message {\r\n max-width: ${v('system-message-max-width')};\r\n padding: ${v('space-2')} ${v('space-6')};\r\n color: ${v('text-system')};\r\n background: ${v('bg-system-message')};\r\n border-radius: ${v('radius-pill')};\r\n font-size: ${v('font-size-sm')};\r\n text-align: center;\r\n}\r\n\r\n.${p}-message-footer {\r\n display: flex;\r\n align-items: center;\r\n gap: ${v('space-3')};\r\n margin-top: ${v('space-1')};\r\n padding: 0 ${v('space-2')};\r\n}\r\n\r\n.${p}-message-row--outgoing .${p}-message-footer {\r\n flex-direction: row-reverse;\r\n}\r\n\r\n.${p}-timestamp,\r\n.${p}-status {\r\n font-size: ${v('font-size-xs')};\r\n}\r\n\r\n.${p}-timestamp {\r\n color: ${v('text-timestamp')};\r\n}\r\n\r\n.${p}-status--sending { color: ${v('color-sending')}; }\r\n.${p}-status--sent { color: ${v('color-sent')}; }\r\n.${p}-status--delivered { color: ${v('color-delivered')}; }\r\n.${p}-status--read { color: ${v('color-read')}; }\r\n.${p}-status--failed {\r\n color: ${v('color-failed')};\r\n cursor: pointer;\r\n}\r\n\r\n.${p}-mention-tag,\r\n.${p}-link {\r\n color: ${v('text-mention-tag')};\r\n font-weight: ${v('font-weight-medium')};\r\n}\r\n\r\n.${p}-mention-tag {\r\n cursor: pointer;\r\n}\r\n\r\n.${p}-mention-tag:hover,\r\n.${p}-link:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.${p}-input-area {\r\n display: flex;\r\n align-items: flex-end;\r\n gap: ${v('space-4')};\r\n position: relative;\r\n padding: ${v('space-5')} ${v('space-6')};\r\n border-top: ${v('border-width')} solid ${v('border-primary')};\r\n background: ${v('bg-input')};\r\n}\r\n\r\n.${p}-input-wrapper {\r\n flex: 1;\r\n min-width: 0;\r\n position: relative;\r\n}\r\n\r\n.${p}-textarea {\r\n width: 100%;\r\n min-height: ${v('textarea-min-height')};\r\n max-height: ${v('textarea-max-height')};\r\n padding: ${v('space-4')} ${v('space-5')};\r\n overflow-y: auto;\r\n resize: none;\r\n outline: none;\r\n color: ${v('text-primary')};\r\n background: ${v('bg-primary')};\r\n border: ${v('border-width')} solid ${v('border-input')};\r\n border-radius: ${v('radius-md')};\r\n font-family: inherit;\r\n font-size: ${v('font-size')};\r\n line-height: ${v('line-height')};\r\n transition: border-color ${v('transition-fast')}, box-shadow ${v('transition-fast')};\r\n}\r\n\r\n.${p}-textarea:focus {\r\n border-color: ${v('border-input-focus')};\r\n box-shadow: 0 0 0 ${v('border-width-drop')} ${v('bg-drop-overlay')};\r\n}\r\n\r\n.${p}-textarea::placeholder {\r\n color: ${v('text-placeholder')};\r\n}\r\n\r\n.${p}-send-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: ${v('input-button-size')};\r\n height: ${v('input-button-size')};\r\n flex-shrink: 0;\r\n color: ${v('btn-primary-text')};\r\n background: ${v('btn-primary-bg')};\r\n border: 0;\r\n border-radius: ${v('radius-md')};\r\n cursor: pointer;\r\n transition: background ${v('transition-fast')}, opacity ${v('transition-fast')};\r\n}\r\n\r\n.${p}-send-btn:hover {\r\n background: ${v('btn-primary-hover')};\r\n}\r\n\r\n.${p}-send-btn:disabled {\r\n cursor: default;\r\n opacity: .5;\r\n}\r\n\r\n.${p}-send-btn svg {\r\n width: var(--ldesign-chat-icon-size);\r\n height: var(--ldesign-chat-icon-size);\r\n}\r\n\r\n.${p}-mention-panel {\r\n position: absolute;\r\n left: 0;\r\n right: 0;\r\n bottom: 100%;\r\n z-index: ${v('z-mention')};\r\n max-height: ${v('panel-max-height')};\r\n margin-bottom: ${v('space-2')};\r\n overflow-y: auto;\r\n background: ${v('bg-mention')};\r\n border: ${v('border-width')} solid ${v('border-mention')};\r\n border-radius: ${v('radius-md')};\r\n box-shadow: ${v('shadow-mention')};\r\n}\r\n\r\n.${p}-mention-item {\r\n display: flex;\r\n align-items: center;\r\n gap: ${v('space-4')};\r\n padding: ${v('space-4')} ${v('space-5')};\r\n color: ${v('text-mention')};\r\n cursor: pointer;\r\n transition: background ${v('transition-fast')};\r\n}\r\n\r\n.${p}-mention-item:hover {\r\n background: ${v('bg-mention-hover')};\r\n}\r\n\r\n.${p}-mention-item--active {\r\n background: ${v('bg-mention-active')};\r\n}\r\n\r\n.${p}-mention-item-avatar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: ${v('mention-avatar-size')};\r\n height: ${v('mention-avatar-size')};\r\n flex-shrink: 0;\r\n overflow: hidden;\r\n color: ${v('avatar-text')};\r\n background: ${v('avatar-bg')};\r\n border-radius: ${v('radius-circle')};\r\n font-size: ${v('font-size-sm')};\r\n font-weight: ${v('font-weight-semibold')};\r\n}\r\n\r\n.${p}-mention-item-avatar img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n.${p}-mention-item-name {\r\n font-size: ${v('font-size')};\r\n}\r\n\r\n.${p}-empty {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n color: ${v('text-secondary')};\r\n font-size: ${v('font-size')};\r\n}\r\n\r\n.${p}-toolbar {\r\n display: flex;\r\n align-items: center;\r\n gap: ${v('space-1')};\r\n padding: ${v('space-3')} ${v('space-4')};\r\n background: ${v('bg-toolbar')};\r\n border-bottom: ${v('border-width')} solid ${v('border-toolbar')};\r\n border-radius: ${v('radius-md')} ${v('radius-md')} 0 0;\r\n}\r\n\r\n.${p}-toolbar-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: ${v('toolbar-button-size')};\r\n height: ${v('toolbar-button-size')};\r\n flex-shrink: 0;\r\n padding: 0;\r\n color: ${v('toolbar-icon-color')};\r\n background: unset;\r\n border: 0;\r\n border-radius: ${v('radius-sm')};\r\n cursor: pointer;\r\n transition: background ${v('transition-fast')}, color ${v('transition-fast')};\r\n}\r\n\r\n.${p}-toolbar-btn svg {\r\n width: var(--ldesign-chat-space-6);\r\n height: var(--ldesign-chat-space-6);\r\n}\r\n\r\n.${p}-toolbar-btn:hover {\r\n color: ${v('toolbar-icon-hover')};\r\n background: ${v('bg-drop-overlay')};\r\n}\r\n\r\n.${p}-toolbar-btn--active {\r\n color: ${v('toolbar-voice-active')};\r\n background: ${v('bg-danger-soft')};\r\n}\r\n\r\n.${p}-toolbar-btn--active:hover {\r\n color: ${v('toolbar-voice-active')};\r\n background: ${v('bg-danger-soft')};\r\n}\r\n\r\n.${p}-drop-overlay {\r\n position: absolute;\r\n inset: 0;\r\n z-index: ${v('z-overlay')};\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n pointer-events: none;\r\n background: ${v('bg-drop-overlay')};\r\n border: ${v('border-width-drop')} dashed ${v('toolbar-icon-hover')};\r\n border-radius: ${v('radius-md')};\r\n}\r\n\r\n.${p}-drop-overlay span {\r\n color: ${v('toolbar-icon-hover')};\r\n font-size: ${v('font-size-sm')};\r\n font-weight: ${v('font-weight-medium')};\r\n}\r\n\r\n@keyframes ${p}-blink {\r\n 0%, 100% { opacity: 1; }\r\n 50% { opacity: 0; }\r\n}\r\n\r\n.${p}-bubble--streaming::after {\r\n content: '';\r\n display: inline-block;\r\n width: ${v('border-width-drop')};\r\n height: 1em;\r\n margin-left: ${v('space-1')};\r\n vertical-align: text-bottom;\r\n background: currentColor;\r\n animation: ${p}-blink 800ms infinite;\r\n}\r\n`\r\n}\r\n\r\nfunction v(name: string): string {\r\n return `var(${COMPONENT_CSS_VAR_PREFIX}-${name})`\r\n}\r\n\r\nfunction toKebab(key: string): string {\r\n return key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)\r\n}\r\n","import type { EventEmitter } from '../core/event-emitter'\r\nimport type { MentionEngine } from '../core/mention-engine'\r\nimport type { ThemeTokens } from '../theme/tokens'\r\nimport type {\r\n ChatConfig,\r\n ChatContentBlock,\r\n ChatMessage,\r\n MentionItem,\r\n MessageStatus,\r\n} from '../types'\r\nimport {\r\n cx,\r\n DEFAULT_CLASS_PREFIX,\r\n normalizeClassPrefix,\r\n} from '../constants/dom'\r\nimport { applyThemeTokens } from './style-manager'\r\n\r\nconst SEND_ICON_SVG =\r\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line><polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon></svg>'\r\nconst ICON_IMAGE =\r\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\"/></svg>'\r\nconst ICON_PAPERCLIP =\r\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/></svg>'\r\nconst ICON_MIC =\r\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/><path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/><line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/></svg>'\r\nconst ICON_MIC_OFF =\r\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\"/><path d=\"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2\"/><path d=\"M5 10v2a7 7 0 0 0 12 5.29\"/><path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\"/><path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\"/><line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/></svg>'\r\nconst FILE_ICON =\r\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\"/><path d=\"M14 2v4a2 2 0 0 0 2 2h4\"/></svg>'\r\n\r\nconst ALLOWED_CUSTOM_TAGS = new Set([\r\n 'a',\r\n 'b',\r\n 'blockquote',\r\n 'br',\r\n 'code',\r\n 'div',\r\n 'em',\r\n 'h1',\r\n 'h2',\r\n 'h3',\r\n 'h4',\r\n 'h5',\r\n 'h6',\r\n 'i',\r\n 'img',\r\n 'li',\r\n 'ol',\r\n 'p',\r\n 'pre',\r\n 's',\r\n 'span',\r\n 'strong',\r\n 'u',\r\n 'ul',\r\n])\r\nconst DANGEROUS_CUSTOM_TAGS = new Set([\r\n 'iframe',\r\n 'object',\r\n 'embed',\r\n 'script',\r\n 'style',\r\n 'svg',\r\n 'math',\r\n 'template',\r\n 'form',\r\n 'input',\r\n 'button',\r\n 'link',\r\n 'meta',\r\n 'base',\r\n])\r\n\r\nconst STATUS_MAP: Record<MessageStatus, string> = {\r\n sending: '...',\r\n sent: '✓',\r\n delivered: '✓✓',\r\n read: '✓✓',\r\n failed: '!',\r\n}\r\n\r\ninterface SpeechRecognitionResultLike {\r\n isFinal: boolean\r\n 0: { transcript: string }\r\n}\r\n\r\ninterface SpeechRecognitionEventLike {\r\n resultIndex?: number\r\n results: ArrayLike<SpeechRecognitionResultLike>\r\n}\r\n\r\ninterface SpeechRecognitionLike {\r\n continuous: boolean\r\n interimResults: boolean\r\n lang: string\r\n onresult: ((event: SpeechRecognitionEventLike) => void) | null\r\n onend: (() => void) | null\r\n onerror: ((error: unknown) => void) | null\r\n start: () => void\r\n stop: () => void\r\n}\r\n\r\nexport class DOMRenderer {\r\n private container: HTMLElement\r\n private document: Document\r\n private config: ChatConfig\r\n private emitter: EventEmitter\r\n private mentionEngine: MentionEngine\r\n private prefix: string\r\n\r\n private root!: HTMLElement\r\n private messageListEl!: HTMLElement\r\n private inputArea: HTMLElement | null = null\r\n private textareaEl: HTMLTextAreaElement | null = null\r\n private sendBtn: HTMLButtonElement | null = null\r\n private mentionPanel: HTMLElement | null = null\r\n private loadMoreEl: HTMLElement | null = null\r\n private toolbarEl: HTMLElement | null = null\r\n private dropOverlay: HTMLElement | null = null\r\n private voiceBtn: HTMLElement | null = null\r\n private loadingMore = false\r\n private isRecording = false\r\n private recognition: SpeechRecognitionLike | null = null\r\n private lastVoiceTranscript = ''\r\n private destroyed = false\r\n private pendingFileInputs = new Set<HTMLInputElement>()\r\n\r\n constructor(\r\n container: HTMLElement,\r\n config: ChatConfig,\r\n emitter: EventEmitter,\r\n mentionEngine: MentionEngine\r\n ) {\r\n this.container = container\r\n this.document = container.ownerDocument\r\n this.config = config\r\n this.emitter = emitter\r\n this.mentionEngine = mentionEngine\r\n this.prefix = normalizeClassPrefix(\r\n config.classPrefix ?? DEFAULT_CLASS_PREFIX\r\n )\r\n }\r\n\r\n init(): void {\r\n if (this.destroyed) return\r\n this.container.innerHTML = ''\r\n this.root = this.el('div', `${this.prefix}-container`)\r\n this.messageListEl = this.el('div', `${this.prefix}-message-list`)\r\n this.root.appendChild(this.messageListEl)\r\n\r\n if (this.config.showInput !== false) {\r\n this.renderInputArea()\r\n }\r\n\r\n this.container.appendChild(this.root)\r\n this.setupEventListeners()\r\n }\r\n\r\n updateMessageContent(id: string, content: string): void {\r\n const rowEl = this.getMessageRow(id)\r\n const bubble = rowEl?.querySelector(\r\n `.${this.prefix}-bubble`\r\n ) as HTMLElement | null\r\n if (!bubble) return\r\n bubble.innerHTML = this.renderTextContent(content)\r\n }\r\n\r\n renderMessages(messages: ChatMessage[]): void {\r\n this.messageListEl.innerHTML = ''\r\n\r\n if (this.config.enableLoadMore) {\r\n this.renderLoadMoreButton()\r\n }\r\n\r\n if (messages.length === 0) {\r\n this.renderEmpty()\r\n return\r\n }\r\n\r\n let lastTimestamp = 0\r\n const interval = this.config.timeGroupInterval ?? 300000\r\n for (const message of messages) {\r\n if (\r\n this.config.showTimestamp !== false &&\r\n message.timestamp - lastTimestamp > interval\r\n ) {\r\n this.renderTimeDivider(message.timestamp)\r\n lastTimestamp = message.timestamp\r\n }\r\n this.renderMessageRow(message)\r\n }\r\n }\r\n\r\n appendMessage(message: ChatMessage): void {\r\n this.removeEmpty()\r\n const messageEls = this.getMessageElements()\r\n const lastTime =\r\n messageEls.length > 0\r\n ? Number.parseInt(\r\n messageEls[messageEls.length - 1].dataset.timestamp ?? '0',\r\n 10\r\n )\r\n : 0\r\n const interval = this.config.timeGroupInterval ?? 300000\r\n\r\n if (\r\n this.config.showTimestamp !== false &&\r\n message.timestamp - lastTime > interval\r\n ) {\r\n this.renderTimeDivider(message.timestamp)\r\n }\r\n\r\n this.renderMessageRow(message)\r\n }\r\n\r\n prependMessages(messages: ChatMessage[]): void {\r\n if (!messages.length) return\r\n this.removeEmpty()\r\n\r\n const scrollHeight = this.messageListEl.scrollHeight\r\n const scrollTop = this.messageListEl.scrollTop\r\n const fragment = this.document.createDocumentFragment()\r\n let lastTimestamp = 0\r\n const interval = this.config.timeGroupInterval ?? 300000\r\n\r\n for (const message of messages) {\r\n if (\r\n this.config.showTimestamp !== false &&\r\n message.timestamp - lastTimestamp > interval\r\n ) {\r\n fragment.appendChild(this.createTimeDivider(message.timestamp))\r\n lastTimestamp = message.timestamp\r\n }\r\n fragment.appendChild(this.createMessageRow(message))\r\n }\r\n\r\n const firstMessage = this.messageListEl.querySelector(\r\n `.${this.prefix}-message-row, .${this.prefix}-time-divider`\r\n )\r\n if (firstMessage) {\r\n firstMessage.before(fragment)\r\n } else if (this.loadMoreEl) {\r\n this.loadMoreEl.after(fragment)\r\n } else {\r\n this.messageListEl.appendChild(fragment)\r\n }\r\n\r\n this.messageListEl.scrollTop =\r\n scrollTop + (this.messageListEl.scrollHeight - scrollHeight)\r\n }\r\n\r\n updateMessage(id: string, message: ChatMessage): void {\r\n const rowEl = this.getMessageRow(id)\r\n if (!rowEl) return\r\n rowEl.replaceWith(this.createMessageRow({ ...message, id }))\r\n }\r\n\r\n removeMessage(id: string): void {\r\n this.getMessageRow(id)?.remove()\r\n this.refreshTimeDividers()\r\n if (this.getMessageElements().length === 0) {\r\n this.renderEmpty()\r\n } else {\r\n this.removeEmpty()\r\n }\r\n }\r\n\r\n scrollToBottom(smooth = true): void {\r\n if (typeof this.messageListEl.scrollTo === 'function') {\r\n this.messageListEl.scrollTo({\r\n top: this.messageListEl.scrollHeight,\r\n behavior: smooth ? 'smooth' : 'auto',\r\n })\r\n return\r\n }\r\n this.messageListEl.scrollTop = this.messageListEl.scrollHeight\r\n }\r\n\r\n isAtBottom(threshold = 4): boolean {\r\n const distance =\r\n this.messageListEl.scrollHeight -\r\n this.messageListEl.scrollTop -\r\n this.messageListEl.clientHeight\r\n return distance <= threshold\r\n }\r\n\r\n setLoadingMore(loading: boolean): void {\r\n this.loadingMore = loading\r\n if (!this.loadMoreEl) return\r\n this.loadMoreEl.textContent = loading\r\n ? '加载中...'\r\n : (this.config.loadMoreText ?? '加载更多')\r\n this.loadMoreEl.classList.toggle(\r\n `${this.prefix}-load-more--loading`,\r\n loading\r\n )\r\n }\r\n\r\n setThemeTokens(tokens: ThemeTokens): void {\r\n if (this.root) applyThemeTokens(this.root, tokens)\r\n }\r\n\r\n getRootElement(): HTMLElement {\r\n return this.root\r\n }\r\n\r\n focusInput(): void {\r\n this.textareaEl?.focus()\r\n }\r\n\r\n setInputContent(content: string): void {\r\n if (!this.textareaEl) return\r\n this.textareaEl.value = this.limitInput(content)\r\n this.autoResize()\r\n this.updateSendButtonState()\r\n this.config.onInputChange?.(this.textareaEl.value)\r\n }\r\n\r\n getInputContent(): string {\r\n return this.textareaEl?.value ?? ''\r\n }\r\n\r\n clearInput(): void {\r\n this.setInputContent('')\r\n }\r\n\r\n renderMentionPanel(members: MentionItem[], activeIndex: number): void {\r\n if (!this.mentionPanel) return\r\n\r\n if (members.length === 0) {\r\n this.mentionPanel.style.display = 'none'\r\n return\r\n }\r\n\r\n this.mentionPanel.style.display = 'block'\r\n this.mentionPanel.innerHTML = ''\r\n\r\n members.forEach((member, index) => {\r\n const item = this.el(\r\n 'div',\r\n cx(\r\n `${this.prefix}-mention-item`,\r\n index === activeIndex && `${this.prefix}-mention-item--active`\r\n )\r\n )\r\n item.setAttribute('role', 'option')\r\n item.setAttribute('aria-selected', String(index === activeIndex))\r\n\r\n const avatar = this.el('div', `${this.prefix}-mention-item-avatar`)\r\n if (member.avatar) {\r\n const img = this.document.createElement('img')\r\n img.src = this.safeResourceUrl(member.avatar)\r\n img.alt = ''\r\n avatar.appendChild(img)\r\n } else {\r\n avatar.textContent = member.name[0]?.toUpperCase() ?? ''\r\n }\r\n item.appendChild(avatar)\r\n\r\n const name = this.el('span', `${this.prefix}-mention-item-name`)\r\n name.textContent = member.name\r\n item.appendChild(name)\r\n\r\n item.addEventListener('mousedown', event => event.preventDefault())\r\n item.addEventListener('click', () => {\r\n const triggerPosition = this.mentionEngine.getState().triggerPosition\r\n const selectionEnd = this.textareaEl?.selectionEnd\r\n const selected = this.mentionEngine.select(index)\r\n if (selected)\r\n this.insertMention(selected, triggerPosition, selectionEnd)\r\n })\r\n\r\n this.mentionPanel?.appendChild(item)\r\n })\r\n }\r\n\r\n hideMentionPanel(): void {\r\n if (this.mentionPanel) {\r\n this.mentionPanel.style.display = 'none'\r\n }\r\n }\r\n\r\n destroy(): void {\r\n if (this.destroyed) return\r\n this.destroyed = true\r\n this.stopVoice()\r\n this.finishVoice()\r\n this.pendingFileInputs.forEach(input => input.remove())\r\n this.pendingFileInputs.clear()\r\n this.root?.remove()\r\n }\r\n\r\n private renderInputArea(): void {\r\n this.inputArea = this.el('div', `${this.prefix}-input-area`)\r\n const wrapper = this.el('div', `${this.prefix}-input-wrapper`)\r\n\r\n this.mentionPanel = this.el('div', `${this.prefix}-mention-panel`)\r\n this.mentionPanel.style.display = 'none'\r\n this.mentionPanel.setAttribute('role', 'listbox')\r\n wrapper.appendChild(this.mentionPanel)\r\n\r\n if (this.config.enableToolbar !== false) {\r\n this.renderToolbar(wrapper)\r\n }\r\n\r\n this.textareaEl = this.document.createElement('textarea')\r\n this.textareaEl.className = `${this.prefix}-textarea`\r\n this.textareaEl.placeholder = this.config.inputPlaceholder ?? '输入消息...'\r\n this.textareaEl.rows = 1\r\n if (this.config.maxInputLength && this.config.maxInputLength > 0) {\r\n this.textareaEl.maxLength = this.config.maxInputLength\r\n }\r\n wrapper.appendChild(this.textareaEl)\r\n\r\n this.dropOverlay = this.el('div', `${this.prefix}-drop-overlay`)\r\n this.dropOverlay.innerHTML = '<span>拖放文件到这里</span>'\r\n this.dropOverlay.style.display = 'none'\r\n wrapper.appendChild(this.dropOverlay)\r\n\r\n this.inputArea.appendChild(wrapper)\r\n\r\n this.sendBtn = this.document.createElement('button')\r\n this.sendBtn.className = `${this.prefix}-send-btn`\r\n this.sendBtn.innerHTML = SEND_ICON_SVG\r\n this.sendBtn.title = '发送'\r\n this.sendBtn.type = 'button'\r\n this.sendBtn.disabled = true\r\n this.inputArea.appendChild(this.sendBtn)\r\n\r\n this.root.appendChild(this.inputArea)\r\n }\r\n\r\n private renderToolbar(wrapper: HTMLElement): void {\r\n const toolbar = this.config.toolbarConfig ?? {}\r\n this.toolbarEl = this.el('div', `${this.prefix}-toolbar`)\r\n\r\n if (toolbar.image !== false) {\r\n const imageBtn = this.createToolbarBtn(ICON_IMAGE, '插入图片')\r\n imageBtn.addEventListener('click', () => this.openFilePicker('image/*'))\r\n this.toolbarEl.appendChild(imageBtn)\r\n }\r\n\r\n if (toolbar.file !== false) {\r\n const fileBtn = this.createToolbarBtn(ICON_PAPERCLIP, '插入文件')\r\n fileBtn.addEventListener('click', () => this.openFilePicker('*/*'))\r\n this.toolbarEl.appendChild(fileBtn)\r\n }\r\n\r\n if (toolbar.voice !== false) {\r\n this.voiceBtn = this.createToolbarBtn(ICON_MIC, '语音输入')\r\n this.voiceBtn.addEventListener('click', () => this.toggleVoice())\r\n this.toolbarEl.appendChild(this.voiceBtn)\r\n }\r\n\r\n wrapper.insertBefore(this.toolbarEl, wrapper.firstChild)\r\n }\r\n\r\n private createToolbarBtn(iconSvg: string, title: string): HTMLButtonElement {\r\n const btn = this.document.createElement('button')\r\n btn.className = `${this.prefix}-toolbar-btn`\r\n btn.innerHTML = iconSvg\r\n btn.title = title\r\n btn.type = 'button'\r\n return btn\r\n }\r\n\r\n private openFilePicker(accept: string): void {\r\n const input = this.document.createElement('input')\r\n input.type = 'file'\r\n input.accept = accept\r\n input.multiple = true\r\n input.style.display = 'none'\r\n this.pendingFileInputs.add(input)\r\n const cleanup = () => {\r\n input.remove()\r\n this.pendingFileInputs.delete(input)\r\n }\r\n input.addEventListener('change', () => {\r\n const files = Array.from(input.files ?? [])\r\n cleanup()\r\n if (!files.length) return\r\n const isImage = accept.startsWith('image')\r\n this.emitter.emit(isImage ? 'toolbar-image' : 'toolbar-file', files)\r\n if (isImage) {\r\n this.config.onImageUpload?.(files)\r\n } else {\r\n this.config.onFileUpload?.(files)\r\n }\r\n })\r\n input.addEventListener('cancel', cleanup)\r\n ;(this.document.body ?? this.document.documentElement).appendChild(input)\r\n input.click()\r\n }\r\n\r\n private toggleVoice(): void {\r\n if (this.isRecording) {\r\n this.stopVoice()\r\n } else {\r\n this.startVoice()\r\n }\r\n }\r\n\r\n private startVoice(): void {\r\n const view = this.document.defaultView as\r\n | (Window & {\r\n SpeechRecognition?: new () => SpeechRecognitionLike\r\n webkitSpeechRecognition?: new () => SpeechRecognitionLike\r\n })\r\n | null\r\n const SpeechRecognition =\r\n view?.SpeechRecognition || view?.webkitSpeechRecognition\r\n if (!SpeechRecognition) {\r\n this.emitter.emit('toolbar-voice-unsupported')\r\n this.config.onVoiceUnsupported?.()\r\n return\r\n }\r\n\r\n try {\r\n this.lastVoiceTranscript = ''\r\n const recognition = new SpeechRecognition()\r\n const finalSegments = new Map<number, string>()\r\n recognition.continuous = false\r\n recognition.interimResults = true\r\n recognition.lang = this.config.voiceLang ?? 'zh-CN'\r\n this.recognition = recognition\r\n\r\n recognition.onresult = event => {\r\n if (this.destroyed || this.recognition !== recognition) return\r\n const firstChangedResult = Math.max(0, event.resultIndex ?? 0)\r\n const newFinalSegments: string[] = []\r\n for (\r\n let index = firstChangedResult;\r\n index < event.results.length;\r\n index++\r\n ) {\r\n const result = event.results[index]\r\n if (!result?.isFinal || finalSegments.has(index)) continue\r\n finalSegments.set(index, result[0].transcript)\r\n newFinalSegments.push(result[0].transcript)\r\n }\r\n this.lastVoiceTranscript = [...finalSegments.entries()]\r\n .sort(([left], [right]) => left - right)\r\n .map(([, transcript]) => transcript)\r\n .join('')\r\n if (newFinalSegments.length && this.textareaEl) {\r\n this.insertTextAtCursor(newFinalSegments.join(''))\r\n }\r\n }\r\n\r\n recognition.onend = () => {\r\n if (this.destroyed || this.recognition !== recognition) return\r\n const transcript = this.lastVoiceTranscript\r\n this.finishVoice()\r\n this.emitter.emit('toolbar-voice-end', transcript)\r\n this.config.onVoiceEnd?.(transcript)\r\n }\r\n\r\n recognition.onerror = error => {\r\n if (this.destroyed || this.recognition !== recognition) return\r\n this.finishVoice()\r\n this.emitter.emit('toolbar-voice-error', error)\r\n this.config.onVoiceError?.(error)\r\n }\r\n\r\n this.isRecording = true\r\n this.voiceBtn?.classList.add(`${this.prefix}-toolbar-btn--active`)\r\n if (this.voiceBtn) this.voiceBtn.innerHTML = ICON_MIC_OFF\r\n recognition.start()\r\n this.emitter.emit('toolbar-voice-start')\r\n this.config.onVoiceStart?.()\r\n } catch (error) {\r\n this.finishVoice()\r\n this.emitter.emit('toolbar-voice-error', error)\r\n this.config.onVoiceError?.(error)\r\n }\r\n }\r\n\r\n private stopVoice(): void {\r\n if (!this.recognition) return\r\n const recognition = this.recognition\r\n try {\r\n recognition.stop()\r\n } catch {\r\n this.finishVoice()\r\n }\r\n }\r\n\r\n private finishVoice(): void {\r\n this.isRecording = false\r\n this.recognition = null\r\n this.voiceBtn?.classList.remove(`${this.prefix}-toolbar-btn--active`)\r\n if (this.voiceBtn) this.voiceBtn.innerHTML = ICON_MIC\r\n }\r\n\r\n private setupEventListeners(): void {\r\n if (this.textareaEl) {\r\n this.textareaEl.addEventListener('input', () => {\r\n const limited = this.limitInput(this.textareaEl?.value ?? '')\r\n if (this.textareaEl && limited !== this.textareaEl.value) {\r\n this.textareaEl.value = limited\r\n }\r\n this.autoResize()\r\n this.updateSendButtonState()\r\n this.config.onInputChange?.(this.textareaEl?.value ?? '')\r\n if (this.config.enableMention && this.textareaEl) {\r\n this.mentionEngine.handleInput(\r\n this.textareaEl.value,\r\n this.textareaEl.selectionStart\r\n )\r\n }\r\n })\r\n\r\n this.textareaEl.addEventListener('keydown', event => {\r\n const mentionState = this.mentionEngine.getState()\r\n\r\n if (mentionState.active) {\r\n if (event.key === 'ArrowUp') {\r\n event.preventDefault()\r\n this.mentionEngine.moveUp()\r\n } else if (event.key === 'ArrowDown') {\r\n event.preventDefault()\r\n this.mentionEngine.moveDown()\r\n } else if (event.key === 'Enter' && !event.shiftKey) {\r\n event.preventDefault()\r\n const triggerPosition = mentionState.triggerPosition\r\n const selectionEnd = this.textareaEl.selectionEnd\r\n const member = this.mentionEngine.selectCurrent()\r\n if (member)\r\n this.insertMention(member, triggerPosition, selectionEnd)\r\n } else if (event.key === 'Escape') {\r\n event.preventDefault()\r\n this.mentionEngine.deactivate()\r\n }\r\n return\r\n }\r\n\r\n if (\r\n this.config.enterToSend !== false &&\r\n event.key === 'Enter' &&\r\n !event.shiftKey\r\n ) {\r\n event.preventDefault()\r\n this.handleSend()\r\n }\r\n })\r\n\r\n this.textareaEl.addEventListener('paste', event => {\r\n const items = event.clipboardData?.items\r\n if (!items) return\r\n const files: File[] = []\r\n for (let i = 0; i < items.length; i++) {\r\n if (items[i].kind === 'file') {\r\n const file = items[i].getAsFile()\r\n if (file) files.push(file)\r\n }\r\n }\r\n if (files.length > 0) {\r\n event.preventDefault()\r\n this.emitter.emit('toolbar-paste', files)\r\n this.config.onPaste?.(files)\r\n }\r\n })\r\n }\r\n\r\n if (this.inputArea) {\r\n const wrapper = this.inputArea.querySelector(\r\n `.${this.prefix}-input-wrapper`\r\n ) as HTMLElement | null\r\n if (wrapper) this.setupDropEvents(wrapper)\r\n }\r\n\r\n this.sendBtn?.addEventListener('click', () => {\r\n this.handleSend()\r\n })\r\n\r\n this.emitter.on(\r\n 'mention-filter',\r\n (state: { filtered: MentionItem[]; activeIndex: number }) => {\r\n this.renderMentionPanel(state.filtered, state.activeIndex)\r\n }\r\n )\r\n this.emitter.on('mention-active-change', (index: number) => {\r\n const items = this.mentionPanel?.querySelectorAll(\r\n `.${this.prefix}-mention-item`\r\n )\r\n items?.forEach((el, i) => {\r\n el.classList.toggle(`${this.prefix}-mention-item--active`, i === index)\r\n el.setAttribute('aria-selected', String(i === index))\r\n })\r\n })\r\n this.emitter.on('mention-deactivate', () => {\r\n this.hideMentionPanel()\r\n })\r\n }\r\n\r\n private setupDropEvents(wrapper: HTMLElement): void {\r\n let dragCounter = 0\r\n wrapper.addEventListener('dragenter', event => {\r\n event.preventDefault()\r\n dragCounter++\r\n if (this.dropOverlay) this.dropOverlay.style.display = 'flex'\r\n })\r\n wrapper.addEventListener('dragleave', event => {\r\n event.preventDefault()\r\n dragCounter--\r\n if (dragCounter <= 0) {\r\n dragCounter = 0\r\n if (this.dropOverlay) this.dropOverlay.style.display = 'none'\r\n }\r\n })\r\n wrapper.addEventListener('dragover', event => {\r\n event.preventDefault()\r\n })\r\n wrapper.addEventListener('drop', event => {\r\n event.preventDefault()\r\n dragCounter = 0\r\n if (this.dropOverlay) this.dropOverlay.style.display = 'none'\r\n const files = Array.from(event.dataTransfer?.files ?? [])\r\n if (files.length > 0) {\r\n this.emitter.emit('toolbar-drop', files)\r\n this.config.onDrop?.(files)\r\n }\r\n })\r\n }\r\n\r\n private handleSend(): void {\r\n const rawContent = this.textareaEl?.value ?? ''\r\n const content = rawContent.trim()\r\n if (!content) return\r\n\r\n const mentions = this.mentionEngine.parseMentions(content)\r\n this.emitter.emit('send', content, mentions)\r\n this.config.onSend?.(content, mentions)\r\n\r\n if (this.config.clearInputOnSend !== false) {\r\n this.clearInput()\r\n }\r\n this.mentionEngine.resetSelected()\r\n }\r\n\r\n private insertMention(\r\n member: MentionItem,\r\n triggerPosition?: number,\r\n selectionEnd?: number\r\n ): void {\r\n if (!this.textareaEl) return\r\n const state = this.mentionEngine.getState()\r\n const text = this.textareaEl.value\r\n const end = selectionEnd ?? this.textareaEl.selectionEnd\r\n const insertText = this.mentionEngine.getInsertText(member)\r\n\r\n const before = text.slice(0, triggerPosition ?? state.triggerPosition)\r\n const after = text.slice(end)\r\n this.textareaEl.value = this.limitInput(before + insertText + after)\r\n const newPos = Math.min(\r\n before.length + insertText.length,\r\n this.textareaEl.value.length\r\n )\r\n this.textareaEl.setSelectionRange(newPos, newPos)\r\n this.textareaEl.focus()\r\n this.autoResize()\r\n this.updateSendButtonState()\r\n this.config.onInputChange?.(this.textareaEl.value)\r\n }\r\n\r\n private insertTextAtCursor(text: string): void {\r\n if (!this.textareaEl) return\r\n const current = this.textareaEl.value\r\n const start = this.textareaEl.selectionStart\r\n const end = this.textareaEl.selectionEnd\r\n this.textareaEl.value = this.limitInput(\r\n current.slice(0, start) + text + current.slice(end)\r\n )\r\n const nextCursor = Math.min(\r\n start + text.length,\r\n this.textareaEl.value.length\r\n )\r\n this.textareaEl.setSelectionRange(nextCursor, nextCursor)\r\n this.autoResize()\r\n this.updateSendButtonState()\r\n this.config.onInputChange?.(this.textareaEl.value)\r\n }\r\n\r\n private autoResize(): void {\r\n if (!this.textareaEl) return\r\n this.textareaEl.style.height = 'auto'\r\n this.textareaEl.style.height = `${this.textareaEl.scrollHeight}px`\r\n }\r\n\r\n private updateSendButtonState(): void {\r\n if (!this.sendBtn) return\r\n this.sendBtn.disabled = !this.getInputContent().trim()\r\n }\r\n\r\n private renderLoadMoreButton(): void {\r\n this.loadMoreEl = this.el('div', `${this.prefix}-load-more`)\r\n this.loadMoreEl.textContent = this.config.loadMoreText ?? '加载更多'\r\n this.loadMoreEl.addEventListener('click', () => {\r\n if (this.destroyed || this.loadingMore) return\r\n this.setLoadingMore(true)\r\n this.emitter.emit('load-more')\r\n void this.loadMore()\r\n })\r\n this.messageListEl.appendChild(this.loadMoreEl)\r\n }\r\n\r\n private async loadMore(): Promise<void> {\r\n try {\r\n await this.config.onLoadMore?.()\r\n } catch (error) {\r\n this.emitter.emit('load-more-error', error)\r\n } finally {\r\n if (!this.destroyed) this.setLoadingMore(false)\r\n }\r\n }\r\n\r\n private renderTimeDivider(timestamp: number): void {\r\n this.messageListEl.appendChild(this.createTimeDivider(timestamp))\r\n }\r\n\r\n private createTimeDivider(timestamp: number): HTMLElement {\r\n const divider = this.el('div', `${this.prefix}-time-divider`)\r\n const span = this.document.createElement('span')\r\n span.textContent = this.formatTime(timestamp)\r\n divider.appendChild(span)\r\n return divider\r\n }\r\n\r\n private renderMessageRow(message: ChatMessage): void {\r\n this.messageListEl.appendChild(this.createMessageRow(message))\r\n }\r\n\r\n private createMessageRow(message: ChatMessage): HTMLElement {\r\n const p = this.prefix\r\n\r\n if (message.type === 'system') {\r\n const row = this.el(\r\n 'div',\r\n cx(`${p}-message-row`, `${p}-message-row--system`)\r\n )\r\n row.dataset.msgId = message.id\r\n row.dataset.timestamp = String(message.timestamp)\r\n const system = this.el('div', `${p}-system-message`)\r\n system.textContent = message.content ?? ''\r\n row.appendChild(system)\r\n return row\r\n }\r\n\r\n const isOutgoing = message.direction === 'outgoing'\r\n const row = this.el(\r\n 'div',\r\n cx(`${p}-message-row`, isOutgoing && `${p}-message-row--outgoing`)\r\n )\r\n row.dataset.msgId = message.id\r\n row.dataset.timestamp = String(message.timestamp)\r\n\r\n if (this.config.showAvatar !== false) {\r\n row.appendChild(\r\n this.createAvatar(message.sender.nickname, message.sender.avatar)\r\n )\r\n }\r\n\r\n const body = this.el('div', `${p}-message-body`)\r\n if (this.config.showNickname !== false && !isOutgoing) {\r\n const nickname = this.el('div', `${p}-nickname`)\r\n nickname.textContent = message.sender.nickname\r\n body.appendChild(nickname)\r\n }\r\n\r\n body.appendChild(this.createBubble(message, isOutgoing))\r\n body.appendChild(this.createMessageFooter(message, isOutgoing))\r\n row.appendChild(body)\r\n\r\n row.addEventListener('click', () => {\r\n this.emitter.emit('message-click', message)\r\n this.config.onMessageClick?.(message)\r\n })\r\n\r\n return row\r\n }\r\n\r\n private createAvatar(name: string, avatarUrl?: string): HTMLElement {\r\n const avatar = this.el('div', `${this.prefix}-avatar`)\r\n if (avatarUrl) {\r\n const img = this.document.createElement('img')\r\n img.src = this.safeResourceUrl(avatarUrl)\r\n img.alt = name\r\n avatar.appendChild(img)\r\n } else {\r\n avatar.textContent = name[0]?.toUpperCase() ?? ''\r\n }\r\n return avatar\r\n }\r\n\r\n private createMessageFooter(\r\n message: ChatMessage,\r\n isOutgoing: boolean\r\n ): HTMLElement {\r\n const footer = this.el('div', `${this.prefix}-message-footer`)\r\n if (this.config.showTimestamp !== false) {\r\n const time = this.el('span', `${this.prefix}-timestamp`)\r\n time.textContent = this.formatShortTime(message.timestamp)\r\n footer.appendChild(time)\r\n }\r\n if (this.config.showStatus !== false && isOutgoing && message.status) {\r\n const status = this.el(\r\n 'span',\r\n cx(`${this.prefix}-status`, `${this.prefix}-status--${message.status}`)\r\n )\r\n status.textContent = STATUS_MAP[message.status] ?? ''\r\n if (message.status === 'failed') {\r\n status.addEventListener('click', event => {\r\n event.stopPropagation()\r\n this.emitter.emit('message-retry', message)\r\n })\r\n }\r\n footer.appendChild(status)\r\n }\r\n return footer\r\n }\r\n\r\n private createBubble(message: ChatMessage, isOutgoing: boolean): HTMLElement {\r\n const p = this.prefix\r\n const dirClass = isOutgoing\r\n ? `${p}-bubble--outgoing`\r\n : `${p}-bubble--incoming`\r\n\r\n if (message.revoked) {\r\n const bubble = this.el(\r\n 'div',\r\n cx(`${p}-bubble`, dirClass, `${p}-bubble--revoked`)\r\n )\r\n bubble.textContent = '消息已撤回'\r\n return bubble\r\n }\r\n\r\n switch (message.type) {\r\n case 'image': {\r\n const bubble = this.el(\r\n 'div',\r\n cx(`${p}-bubble`, dirClass, `${p}-bubble--image`)\r\n )\r\n if (message.image) {\r\n const img = this.document.createElement('img')\r\n img.src = this.safeResourceUrl(\r\n message.image.thumbUrl ?? message.image.url\r\n )\r\n img.alt = message.content ?? ''\r\n if (message.image.width)\r\n img.width = Math.min(message.image.width, 240)\r\n bubble.appendChild(img)\r\n }\r\n return bubble\r\n }\r\n\r\n case 'file': {\r\n const bubble = this.el(\r\n 'div',\r\n cx(`${p}-bubble`, dirClass, `${p}-bubble--file`)\r\n )\r\n const icon = this.el('div', `${p}-file-icon`)\r\n icon.innerHTML = FILE_ICON\r\n bubble.appendChild(icon)\r\n\r\n const info = this.el('div', `${p}-file-info`)\r\n const name = this.el('div', `${p}-file-name`)\r\n name.textContent = message.file?.name ?? 'file'\r\n info.appendChild(name)\r\n\r\n if (message.file?.size) {\r\n const size = this.el('div', `${p}-file-size`)\r\n size.textContent = this.formatFileSize(message.file.size)\r\n info.appendChild(size)\r\n }\r\n bubble.appendChild(info)\r\n return bubble\r\n }\r\n\r\n case 'custom': {\r\n const bubble = this.el('div', cx(`${p}-bubble`, dirClass))\r\n if (message.customHtml) {\r\n this.setSanitizedCustomHtml(bubble, message.customHtml)\r\n } else {\r\n bubble.textContent = message.content ?? ''\r\n }\r\n return bubble\r\n }\r\n\r\n default: {\r\n const bubble = this.el(\r\n 'div',\r\n cx(\r\n `${p}-bubble`,\r\n dirClass,\r\n message.streaming && `${p}-bubble--streaming`\r\n )\r\n )\r\n if (message.contentBlocks?.length) {\r\n this.renderContentBlocks(bubble, message.contentBlocks)\r\n } else {\r\n bubble.innerHTML = this.renderTextContent(\r\n message.content ?? '',\r\n message.mentions\r\n )\r\n }\r\n return bubble\r\n }\r\n }\r\n }\r\n\r\n private renderContentBlocks(\r\n target: HTMLElement,\r\n blocks: ChatContentBlock[]\r\n ): void {\r\n target.replaceChildren()\r\n for (const block of blocks) {\r\n switch (block.type) {\r\n case 'text':\r\n target.appendChild(this.document.createTextNode(block.text))\r\n break\r\n case 'mention': {\r\n const mention = this.el('span', `${this.prefix}-mention-tag`)\r\n mention.dataset.mentionId = block.id\r\n mention.textContent = `@${block.label}`\r\n target.appendChild(mention)\r\n break\r\n }\r\n case 'link': {\r\n const link = this.document.createElement('a')\r\n const safeUrl = this.safeUrl(block.url, [\r\n 'http:',\r\n 'https:',\r\n 'mailto:',\r\n ])\r\n link.className = `${this.prefix}-link`\r\n link.textContent = block.label ?? block.url\r\n if (safeUrl) {\r\n link.href = safeUrl\r\n link.target = '_blank'\r\n link.rel = 'noopener noreferrer'\r\n }\r\n target.appendChild(link)\r\n break\r\n }\r\n case 'code': {\r\n const code = this.document.createElement('code')\r\n code.textContent = block.code\r\n if (block.language) code.dataset.language = block.language\r\n target.appendChild(code)\r\n break\r\n }\r\n case 'image': {\r\n const image = this.document.createElement('img')\r\n const safeUrl = this.safeResourceUrl(block.src)\r\n const width = block.width\r\n const height = block.height\r\n if (safeUrl) image.src = safeUrl\r\n image.alt = block.alt ?? ''\r\n image.loading = 'lazy'\r\n if (Number.isFinite(width) && width > 0) {\r\n image.width = width\r\n }\r\n if (Number.isFinite(height) && height > 0) {\r\n image.height = height\r\n }\r\n target.appendChild(image)\r\n break\r\n }\r\n case 'file': {\r\n const file = this.document.createElement('a')\r\n const safeUrl = this.safeResourceUrl(block.url)\r\n file.className = `${this.prefix}-file-link`\r\n file.textContent = block.name\r\n if (safeUrl) {\r\n file.href = safeUrl\r\n file.target = '_blank'\r\n file.rel = 'noopener noreferrer'\r\n }\r\n target.appendChild(file)\r\n break\r\n }\r\n case 'break':\r\n target.appendChild(this.document.createElement('br'))\r\n break\r\n case 'custom':\r\n target.appendChild(\r\n this.document.createTextNode(block.fallback ?? `[${block.kind}]`)\r\n )\r\n break\r\n }\r\n }\r\n }\r\n\r\n private renderTextContent(content: string, mentions?: MentionItem[]): string {\r\n let html = this.escapeHtml(content)\r\n\r\n if (mentions?.length) {\r\n for (const mention of mentions) {\r\n const tag = `<span class=\"${this.prefix}-mention-tag\" data-mention-id=\"${this.escapeAttr(mention.id)}\">@${this.escapeHtml(mention.name)}</span>`\r\n html = html.replace(\r\n new RegExp(`@${this.escapeRegex(mention.name)}`, 'g'),\r\n tag\r\n )\r\n }\r\n }\r\n\r\n return html.replace(\r\n /(https?:\\/\\/[^\\s<]+)/g,\r\n `<a class=\"${this.prefix}-link\" href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>`\r\n )\r\n }\r\n\r\n private setSanitizedCustomHtml(target: HTMLElement, html: string): void {\r\n const template = this.document.createElement('template')\r\n template.innerHTML = html\r\n const fragment = this.document.createDocumentFragment()\r\n for (const node of Array.from(template.content.childNodes)) {\r\n const sanitized = this.sanitizeCustomNode(node)\r\n if (sanitized) fragment.appendChild(sanitized)\r\n }\r\n target.replaceChildren(fragment)\r\n }\r\n\r\n private sanitizeCustomNode(node: Node): Node | null {\r\n if (node.nodeType === 3) {\r\n return this.document.createTextNode(node.textContent ?? '')\r\n }\r\n if (node.nodeType !== 1) return null\r\n\r\n const source = node as Element\r\n const tagName = source.tagName.toLowerCase()\r\n if (DANGEROUS_CUSTOM_TAGS.has(tagName)) return null\r\n\r\n if (!ALLOWED_CUSTOM_TAGS.has(tagName)) {\r\n const fragment = this.document.createDocumentFragment()\r\n for (const child of Array.from(source.childNodes)) {\r\n const sanitized = this.sanitizeCustomNode(child)\r\n if (sanitized) fragment.appendChild(sanitized)\r\n }\r\n return fragment\r\n }\r\n\r\n const element = this.document.createElement(tagName)\r\n const title = source.getAttribute('title')\r\n if (title) element.setAttribute('title', title)\r\n const ariaLabel = source.getAttribute('aria-label')\r\n if (ariaLabel) element.setAttribute('aria-label', ariaLabel)\r\n\r\n if (tagName === 'a') {\r\n const href = source.getAttribute('href')\r\n const safeHref = href\r\n ? this.safeUrl(href, ['http:', 'https:', 'mailto:'])\r\n : null\r\n if (safeHref) element.setAttribute('href', safeHref)\r\n const target = source.getAttribute('target')\r\n if (target === '_blank' || target === '_self')\r\n element.setAttribute('target', target)\r\n element.setAttribute('rel', 'noopener noreferrer')\r\n }\r\n\r\n if (tagName === 'img') {\r\n const src = source.getAttribute('src')\r\n const safeSrc = src\r\n ? this.safeUrl(src, ['http:', 'https:', 'blob:'])\r\n : null\r\n if (safeSrc) element.setAttribute('src', safeSrc)\r\n element.setAttribute('alt', source.getAttribute('alt') ?? '')\r\n for (const dimension of ['width', 'height'] as const) {\r\n const value = Number(source.getAttribute(dimension))\r\n if (Number.isFinite(value) && value > 0)\r\n element.setAttribute(dimension, String(value))\r\n }\r\n element.setAttribute('loading', 'lazy')\r\n }\r\n\r\n for (const child of Array.from(source.childNodes)) {\r\n const sanitized = this.sanitizeCustomNode(child)\r\n if (sanitized) element.appendChild(sanitized)\r\n }\r\n return element\r\n }\r\n\r\n private safeResourceUrl(value?: string): string {\r\n if (!value) return ''\r\n return this.safeUrl(value, ['http:', 'https:', 'blob:']) ?? ''\r\n }\r\n\r\n private safeUrl(value: string, protocols: string[]): string | null {\r\n const trimmed = value.trim()\r\n if (\r\n !trimmed ||\r\n [...trimmed].some(character => {\r\n const code = character.charCodeAt(0)\r\n return code < 32 || code === 127\r\n })\r\n )\r\n return null\r\n try {\r\n const resolved = new URL(trimmed, this.document.baseURI)\r\n return protocols.includes(resolved.protocol) ? trimmed : null\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n private renderEmpty(): void {\r\n if (this.messageListEl.querySelector(`.${this.prefix}-empty`)) return\r\n const empty = this.el('div', `${this.prefix}-empty`)\r\n empty.textContent = '暂无消息'\r\n this.messageListEl.appendChild(empty)\r\n }\r\n\r\n private removeEmpty(): void {\r\n this.messageListEl.querySelector(`.${this.prefix}-empty`)?.remove()\r\n }\r\n\r\n private el(tag: string, className: string): HTMLElement {\r\n const el = this.document.createElement(tag)\r\n el.className = className\r\n return el\r\n }\r\n\r\n private getMessageElements(): HTMLElement[] {\r\n return Array.from(\r\n this.messageListEl.querySelectorAll<HTMLElement>(\r\n `.${this.prefix}-message-row`\r\n )\r\n )\r\n }\r\n\r\n private getMessageRow(id: string): HTMLElement | null {\r\n return (\r\n this.getMessageElements().find(element => element.dataset.msgId === id) ??\r\n null\r\n )\r\n }\r\n\r\n private refreshTimeDividers(): void {\r\n this.messageListEl\r\n .querySelectorAll(`.${this.prefix}-time-divider`)\r\n .forEach(divider => divider.remove())\r\n const interval = this.config.timeGroupInterval ?? 300000\r\n let previousTimestamp = 0\r\n for (const row of this.getMessageElements()) {\r\n const timestamp = Number(row.dataset.timestamp ?? 0)\r\n if (\r\n this.config.showTimestamp !== false &&\r\n timestamp - previousTimestamp > interval\r\n ) {\r\n row.before(this.createTimeDivider(timestamp))\r\n }\r\n previousTimestamp = timestamp\r\n }\r\n }\r\n\r\n private formatTime(timestamp: number): string {\r\n if (this.config.formatTime) return this.config.formatTime(timestamp)\r\n const date = new Date(timestamp)\r\n const now = new Date()\r\n const isToday = date.toDateString() === now.toDateString()\r\n if (isToday) {\r\n return date.toLocaleTimeString('zh-CN', {\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n })\r\n }\r\n return date.toLocaleDateString('zh-CN', {\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n })\r\n }\r\n\r\n private formatShortTime(timestamp: number): string {\r\n return new Date(timestamp).toLocaleTimeString('zh-CN', {\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n })\r\n }\r\n\r\n private formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\r\n }\r\n\r\n private limitInput(content: string): string {\r\n const max = this.config.maxInputLength\r\n if (!max || max <= 0) return content\r\n return content.slice(0, max)\r\n }\r\n\r\n private escapeHtml(str: string): string {\r\n const div = this.document.createElement('div')\r\n div.textContent = str\r\n return div.innerHTML\r\n }\r\n\r\n private escapeAttr(str: string): string {\r\n return str\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#39;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n }\r\n\r\n private escapeRegex(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\r\n }\r\n}\r\n","/**\r\n * @file tokens.ts\r\n * @description tokens 模块\r\n */\r\n\r\n/**\r\n * ThemeTokens interface\r\n */\r\nexport interface ThemeTokens {\r\n bgPrimary: string\r\n bgSecondary: string\r\n bgBubbleOutgoing: string\r\n bgBubbleIncoming: string\r\n bgInput: string\r\n bgMention: string\r\n bgMentionHover: string\r\n bgMentionActive: string\r\n bgLoadMore: string\r\n bgSystemMessage: string\r\n bgDropOverlay: string\r\n bgDangerSoft: string\r\n\r\n textPrimary: string\r\n textSecondary: string\r\n textBubbleOutgoing: string\r\n textBubbleIncoming: string\r\n textMention: string\r\n textMentionTag: string\r\n textTimestamp: string\r\n textSystem: string\r\n textPlaceholder: string\r\n\r\n borderPrimary: string\r\n borderInput: string\r\n borderInputFocus: string\r\n borderMention: string\r\n\r\n colorSending: string\r\n colorSent: string\r\n colorDelivered: string\r\n colorRead: string\r\n colorFailed: string\r\n colorLink: string\r\n\r\n shadowPanel: string\r\n shadowMention: string\r\n\r\n avatarBg: string\r\n avatarText: string\r\n\r\n btnPrimaryBg: string\r\n btnPrimaryText: string\r\n btnPrimaryHover: string\r\n\r\n scrollbarThumb: string\r\n scrollbarTrack: string\r\n\r\n bgToolbar: string\r\n borderToolbar: string\r\n toolbarIconColor: string\r\n toolbarIconHover: string\r\n toolbarVoiceActive: string\r\n}\r\n\r\nexport const lightTokens: ThemeTokens = {\r\n bgPrimary: 'var(--ld-bg-surface)',\r\n bgSecondary: 'var(--ld-bg-surface-soft)',\r\n bgBubbleOutgoing: 'var(--ld-primary-default)',\r\n bgBubbleIncoming: 'var(--ld-bg-surface-soft)',\r\n bgInput: 'var(--ld-bg-surface)',\r\n bgMention: 'var(--ld-bg-surface)',\r\n bgMentionHover: 'var(--ld-primary-50)',\r\n bgMentionActive: 'var(--ld-primary-100)',\r\n bgLoadMore: 'var(--ld-bg-surface-soft)',\r\n bgSystemMessage: 'var(--ld-bg-surface-soft)',\r\n bgDropOverlay:\r\n 'color-mix(in srgb, var(--ld-primary-default) 10%, var(--ld-bg-surface))',\r\n bgDangerSoft:\r\n 'color-mix(in srgb, var(--ld-danger-default) 12%, var(--ld-bg-surface))',\r\n\r\n textPrimary: 'var(--ld-text-primary)',\r\n textSecondary: 'var(--ld-text-secondary)',\r\n textBubbleOutgoing: 'var(--ld-gray-50)',\r\n textBubbleIncoming: 'var(--ld-text-primary)',\r\n textMention: 'var(--ld-text-primary)',\r\n textMentionTag: 'var(--ld-primary-default)',\r\n textTimestamp: 'var(--ld-text-muted)',\r\n textSystem: 'var(--ld-text-secondary)',\r\n textPlaceholder: 'var(--ld-text-muted)',\r\n\r\n borderPrimary: 'var(--ld-border)',\r\n borderInput: 'var(--ld-gray-300)',\r\n borderInputFocus: 'var(--ld-primary-default)',\r\n borderMention: 'var(--ld-border)',\r\n\r\n colorSending: 'var(--ld-gray-400)',\r\n colorSent: 'var(--ld-gray-500)',\r\n colorDelivered: 'var(--ld-primary-default)',\r\n colorRead: 'var(--ld-success-default)',\r\n colorFailed: 'var(--ld-danger-default)',\r\n colorLink: 'var(--ld-primary-default)',\r\n\r\n shadowPanel: 'none',\r\n shadowMention: 'none',\r\n\r\n avatarBg: 'var(--ld-primary-default)',\r\n avatarText: 'var(--ld-gray-50)',\r\n\r\n btnPrimaryBg: 'var(--ld-primary-default)',\r\n btnPrimaryText: 'var(--ld-gray-50)',\r\n btnPrimaryHover: 'var(--ld-primary-hover)',\r\n\r\n scrollbarThumb: 'var(--ld-gray-300)',\r\n scrollbarTrack: 'var(--ld-gray-100)',\r\n\r\n bgToolbar: 'var(--ld-bg-surface-soft)',\r\n borderToolbar: 'var(--ld-border)',\r\n toolbarIconColor: 'var(--ld-text-secondary)',\r\n toolbarIconHover: 'var(--ld-primary-default)',\r\n toolbarVoiceActive: 'var(--ld-danger-default)',\r\n}\r\n\r\nexport const darkTokens: ThemeTokens = {\r\n bgPrimary: 'var(--ld-gray-900)',\r\n bgSecondary: 'var(--ld-gray-800)',\r\n bgBubbleOutgoing: 'var(--ld-primary-default)',\r\n bgBubbleIncoming: 'var(--ld-gray-800)',\r\n bgInput: 'var(--ld-gray-900)',\r\n bgMention: 'var(--ld-gray-900)',\r\n bgMentionHover: 'var(--ld-gray-800)',\r\n bgMentionActive: 'var(--ld-primary-900)',\r\n bgLoadMore: 'var(--ld-gray-800)',\r\n bgSystemMessage: 'var(--ld-gray-800)',\r\n bgDropOverlay:\r\n 'color-mix(in srgb, var(--ld-primary-default) 16%, var(--ld-gray-900))',\r\n bgDangerSoft:\r\n 'color-mix(in srgb, var(--ld-danger-default) 18%, var(--ld-gray-900))',\r\n\r\n textPrimary: 'var(--ld-gray-50)',\r\n textSecondary: 'var(--ld-gray-300)',\r\n textBubbleOutgoing: 'var(--ld-gray-50)',\r\n textBubbleIncoming: 'var(--ld-gray-50)',\r\n textMention: 'var(--ld-gray-50)',\r\n textMentionTag: 'var(--ld-primary-300)',\r\n textTimestamp: 'var(--ld-gray-400)',\r\n textSystem: 'var(--ld-gray-300)',\r\n textPlaceholder: 'var(--ld-gray-500)',\r\n\r\n borderPrimary: 'var(--ld-gray-700)',\r\n borderInput: 'var(--ld-gray-700)',\r\n borderInputFocus: 'var(--ld-primary-default)',\r\n borderMention: 'var(--ld-gray-700)',\r\n\r\n colorSending: 'var(--ld-gray-500)',\r\n colorSent: 'var(--ld-gray-400)',\r\n colorDelivered: 'var(--ld-primary-300)',\r\n colorRead: 'var(--ld-success-default)',\r\n colorFailed: 'var(--ld-danger-default)',\r\n colorLink: 'var(--ld-primary-300)',\r\n\r\n shadowPanel: 'none',\r\n shadowMention: 'none',\r\n\r\n avatarBg: 'var(--ld-primary-default)',\r\n avatarText: 'var(--ld-gray-50)',\r\n\r\n btnPrimaryBg: 'var(--ld-primary-default)',\r\n btnPrimaryText: 'var(--ld-gray-50)',\r\n btnPrimaryHover: 'var(--ld-primary-hover)',\r\n\r\n scrollbarThumb: 'var(--ld-gray-700)',\r\n scrollbarTrack: 'var(--ld-gray-800)',\r\n\r\n bgToolbar: 'var(--ld-gray-800)',\r\n borderToolbar: 'var(--ld-gray-700)',\r\n toolbarIconColor: 'var(--ld-gray-300)',\r\n toolbarIconHover: 'var(--ld-primary-300)',\r\n toolbarVoiceActive: 'var(--ld-danger-default)',\r\n}\r\n","/**\r\n * 主题管理器\r\n */\r\n\r\nimport type { EventEmitter } from '../core/event-emitter'\r\nimport type { ThemeMode } from '../types'\r\nimport type { ThemeTokens } from './tokens'\r\nimport { darkTokens, lightTokens } from './tokens'\r\n\r\n/**\r\n * ThemeManager - Theme Manager class\r\n */\r\nexport class ThemeManager {\r\n private mode: ThemeMode = 'light'\r\n private emitter: EventEmitter\r\n private mediaQuery: MediaQueryList | null = null\r\n private mediaHandler: ((e: MediaQueryListEvent) => void) | null = null\r\n private view: Window | null\r\n private destroyed = false\r\n\r\n constructor(emitter: EventEmitter, mode?: ThemeMode, view?: Window | null) {\r\n this.emitter = emitter\r\n this.view =\r\n view === undefined\r\n ? typeof window === 'undefined'\r\n ? null\r\n : window\r\n : view\r\n if (mode) this.setTheme(mode)\r\n }\r\n\r\n /** 获取当前模式 */\r\n getMode(): ThemeMode {\r\n return this.mode\r\n }\r\n\r\n /** 获取当前实际主题(auto 时解析为 light/dark) */\r\n getResolvedTheme(): 'light' | 'dark' {\r\n if (this.mode === 'auto') {\r\n return this.getSystemTheme()\r\n }\r\n return this.mode\r\n }\r\n\r\n /** 获取当前主题令牌 */\r\n getTokens(): ThemeTokens {\r\n return this.getResolvedTheme() === 'dark' ? darkTokens : lightTokens\r\n }\r\n\r\n /** 设置主题 */\r\n setTheme(mode: ThemeMode): void {\r\n if (this.destroyed) return\r\n this.cleanupMediaListener()\r\n this.mode = mode\r\n\r\n if (mode === 'auto') {\r\n this.setupMediaListener()\r\n }\r\n\r\n this.emitter.emit('theme-change', this.getResolvedTheme(), this.getTokens())\r\n }\r\n\r\n /** 获取系统主题偏好 */\r\n private getSystemTheme(): 'light' | 'dark' {\r\n const matchMedia = this.view?.matchMedia\r\n if (!matchMedia) return 'light'\r\n return matchMedia.call(this.view, '(prefers-color-scheme: dark)').matches\r\n ? 'dark'\r\n : 'light'\r\n }\r\n\r\n /** 监听系统主题变化 */\r\n private setupMediaListener(): void {\r\n if (!this.view?.matchMedia) return\r\n this.mediaQuery = this.view.matchMedia('(prefers-color-scheme: dark)')\r\n this.mediaHandler = () => {\r\n this.emitter.emit(\r\n 'theme-change',\r\n this.getResolvedTheme(),\r\n this.getTokens()\r\n )\r\n }\r\n const query = this.mediaQuery as unknown as {\r\n addEventListener?: (\r\n type: 'change',\r\n listener: (event: MediaQueryListEvent) => void\r\n ) => void\r\n addListener?: (listener: (event: MediaQueryListEvent) => void) => void\r\n }\r\n if (typeof query.addEventListener === 'function') {\r\n query.addEventListener('change', this.mediaHandler)\r\n } else {\r\n query.addListener?.(this.mediaHandler)\r\n }\r\n }\r\n\r\n /** 清理监听器 */\r\n private cleanupMediaListener(): void {\r\n if (this.mediaQuery && this.mediaHandler) {\r\n const query = this.mediaQuery as unknown as {\r\n removeEventListener?: (\r\n type: 'change',\r\n listener: (event: MediaQueryListEvent) => void\r\n ) => void\r\n removeListener?: (\r\n listener: (event: MediaQueryListEvent) => void\r\n ) => void\r\n }\r\n if (typeof query.removeEventListener === 'function') {\r\n query.removeEventListener('change', this.mediaHandler)\r\n } else {\r\n query.removeListener?.(this.mediaHandler)\r\n }\r\n this.mediaQuery = null\r\n this.mediaHandler = null\r\n }\r\n }\r\n\r\n /** 销毁 */\r\n destroy(): void {\r\n if (this.destroyed) return\r\n this.destroyed = true\r\n this.cleanupMediaListener()\r\n }\r\n}\r\n","import type { ChatMessage } from '../types'\nimport { cloneChatMessage, normalizeChatMessage } from './message-schema'\n\n/** 离线 outbox 中的一条待发送消息。 */\nexport interface ChatOutboxEntry {\n id: string\n message: ChatMessage\n enqueuedAt: number\n attempts: number\n state: 'pending' | 'failed'\n lastError?: string\n}\n\n/** outbox 持久化适配器;可接 IndexedDB、SQLite bridge 或业务缓存。 */\nexport interface ChatOutboxStorage {\n load: () => ChatOutboxEntry[] | Promise<ChatOutboxEntry[]>\n save: (entries: ChatOutboxEntry[]) => void | Promise<void>\n}\n\n/** 内存适配器,适合默认运行和单元测试。 */\nexport class MemoryChatOutboxStorage implements ChatOutboxStorage {\n private entries: ChatOutboxEntry[] = []\n\n load(): ChatOutboxEntry[] {\n return cloneEntries(this.entries)\n }\n\n save(entries: ChatOutboxEntry[]): void {\n this.entries = cloneEntries(entries)\n }\n}\n\nexport interface ChatOutboxOptions {\n storage?: ChatOutboxStorage\n now?: () => number\n}\n\nexport interface ChatOutboxFlushOptions {\n signal?: AbortSignal\n maxAttempts?: number\n concurrency?: number\n}\n\nexport interface ChatOutboxFlushResult {\n sent: string[]\n failed: Array<{ id: string; error: unknown }>\n remaining: ChatOutboxEntry[]\n}\n\n/**\n * 幂等离线队列。\n *\n * 队列只负责保存和重试,不假设网络协议;发送函数由 ChatTransportController\n * 或业务层注入。每条消息以 clientMessageId 优先作为幂等键,重复 enqueue 不会产生重复项。\n */\nexport class ChatOutbox {\n private readonly storage: ChatOutboxStorage\n private readonly now: () => number\n private entries: ChatOutboxEntry[] = []\n private hydrated = false\n private writePromise: Promise<void> = Promise.resolve()\n\n constructor(options: ChatOutboxOptions = {}) {\n this.storage = options.storage ?? new MemoryChatOutboxStorage()\n this.now = options.now ?? Date.now\n }\n\n async hydrate(): Promise<ChatOutboxEntry[]> {\n if (!this.hydrated) {\n this.entries = (await this.storage.load()).map(normalizeEntry)\n this.hydrated = true\n }\n return this.list()\n }\n\n list(): ChatOutboxEntry[] {\n return cloneEntries(this.entries)\n }\n\n async enqueue(message: ChatMessage): Promise<ChatOutboxEntry> {\n await this.hydrate()\n const normalized = normalizeChatMessage({\n ...message,\n clientMessageId: message.clientMessageId ?? message.id,\n })\n const key = getOutboxKey(normalized)\n const existing = this.entries.find(entry => entry.id === key)\n if (existing) return cloneEntry(existing)\n\n const entry: ChatOutboxEntry = {\n id: key,\n message: normalized,\n enqueuedAt: this.now(),\n attempts: 0,\n state: 'pending',\n }\n this.entries.push(entry)\n await this.persist()\n return cloneEntry(entry)\n }\n\n async remove(id: string): Promise<boolean> {\n await this.hydrate()\n const index = this.entries.findIndex(entry => entry.id === id)\n if (index < 0) return false\n this.entries.splice(index, 1)\n await this.persist()\n return true\n }\n\n async retry(id?: string): Promise<void> {\n await this.hydrate()\n for (const entry of this.entries) {\n if (!id || entry.id === id) {\n entry.state = 'pending'\n entry.lastError = undefined\n }\n }\n await this.persist()\n }\n\n async clear(): Promise<void> {\n await this.hydrate()\n this.entries = []\n await this.persist()\n }\n\n async flush(\n send: (\n message: ChatMessage,\n options: { signal?: AbortSignal; clientMessageId: string }\n ) => Promise<unknown>,\n options: ChatOutboxFlushOptions = {}\n ): Promise<ChatOutboxFlushResult> {\n await this.hydrate()\n const maxAttempts = Math.max(1, Math.floor(options.maxAttempts ?? 3))\n const concurrency = Math.min(\n 8,\n Math.max(1, Math.floor(options.concurrency ?? 1))\n )\n const candidates = this.entries.filter(entry => entry.state === 'pending')\n const sent: string[] = []\n const failed: Array<{ id: string; error: unknown }> = []\n let cursor = 0\n\n const worker = async () => {\n while (cursor < candidates.length) {\n if (options.signal?.aborted) throw createAbortError()\n const entry = candidates[cursor++]\n entry.attempts += 1\n try {\n await send(entry.message, {\n signal: options.signal,\n clientMessageId: entry.message.clientMessageId ?? entry.id,\n })\n const index = this.entries.findIndex(item => item.id === entry.id)\n if (index >= 0) this.entries.splice(index, 1)\n sent.push(entry.id)\n } catch (error) {\n entry.lastError = toErrorMessage(error)\n if (entry.attempts >= maxAttempts) entry.state = 'failed'\n failed.push({ id: entry.id, error })\n }\n await this.persist()\n }\n }\n\n await Promise.all(Array.from({ length: concurrency }, () => worker()))\n return { sent, failed, remaining: this.list() }\n }\n\n private async persist(): Promise<void> {\n const snapshot = cloneEntries(this.entries)\n const previous = this.writePromise\n this.writePromise = previous.then(() => this.storage.save(snapshot))\n await this.writePromise\n }\n}\n\nfunction getOutboxKey(message: ChatMessage): string {\n return message.clientMessageId ?? message.id\n}\n\nfunction cloneEntry(entry: ChatOutboxEntry): ChatOutboxEntry {\n return {\n ...entry,\n message: cloneChatMessage(entry.message),\n }\n}\n\nfunction cloneEntries(entries: ChatOutboxEntry[]): ChatOutboxEntry[] {\n return entries.map(cloneEntry)\n}\n\nfunction normalizeEntry(entry: ChatOutboxEntry): ChatOutboxEntry {\n const message = normalizeChatMessage(entry.message)\n const id =\n typeof entry.id === 'string' && entry.id ? entry.id : getOutboxKey(message)\n const enqueuedAt = Number.isFinite(entry.enqueuedAt)\n ? entry.enqueuedAt\n : Date.now()\n const attempts = Number.isFinite(entry.attempts)\n ? Math.max(0, Math.floor(entry.attempts))\n : 0\n const state = entry.state === 'failed' ? 'failed' : 'pending'\n return {\n id,\n message,\n enqueuedAt,\n attempts,\n state,\n ...(typeof entry.lastError === 'string' && {\n lastError: entry.lastError,\n }),\n }\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction createAbortError(): DOMException {\n return new DOMException('The operation was aborted.', 'AbortError')\n}\n","/**\r\n * @composy/chat-core - 即时通讯/IM 组件核心库\r\n *\r\n * 提供聊天气泡、消息列表、@提及、多消息类型(文本/图片/文件/系统消息/自定义)、\r\n * 消息状态管理(发送中/已发送/已送达/已读/失败)、亮暗主题切换等能力。\r\n * 框架无关的核心实现,配合 Vue/React 适配层使用。\r\n *\r\n * @packageDocumentation\r\n * @module @composy/chat-core\r\n */\r\n\r\nimport type { ChatOutboxFlushOptions } from './core/outbox'\r\nimport type {\r\n ChatTransportAck,\r\n ChatTransportEvent,\r\n ChatTransportStatus,\r\n} from './core/transport'\r\nimport type { ThemeTokens } from './theme/tokens'\r\nimport type {\r\n ChatConfig,\r\n ChatInstance,\r\n ChatMessage,\r\n MentionItem,\r\n ThemeMode,\r\n} from './types'\r\nimport { DEFAULT_CLASS_PREFIX, normalizeClassPrefix } from './constants/dom'\r\nimport { ChatManager } from './core/chat-manager'\r\nimport { EventEmitter } from './core/event-emitter'\r\nimport { MentionEngine } from './core/mention-engine'\r\nimport { normalizeChatMessage } from './core/message-schema'\r\nimport { ChatTransportController } from './core/transport'\r\nimport { DOMRenderer } from './renderer/dom-renderer'\r\nimport { injectStyles, removeStyles } from './renderer/style-manager'\r\nimport { ThemeManager } from './theme/theme-manager'\r\n\r\nexport const version = '0.1.0'\r\n\r\nexport {\r\n COMPONENT_CSS_VAR_PREFIX,\r\n cx,\r\n DEFAULT_CLASS_PREFIX,\r\n getStyleElementId,\r\n normalizeClassPrefix,\r\n STYLE_ELEMENT_ID,\r\n} from './constants/dom'\r\n\r\nexport { ChatManager } from './core/chat-manager'\r\nexport type {\r\n MessageMergeOptions,\r\n MessageMergeResult,\r\n StreamAppendOptions,\r\n} from './core/chat-manager'\r\n// Core\r\nexport { EventEmitter } from './core/event-emitter'\r\nexport { MentionEngine } from './core/mention-engine'\r\nexport type { MentionState } from './core/mention-engine'\r\nexport {\r\n cloneChatMessage,\r\n compareChatMessages,\r\n normalizeChatContentBlocks,\r\n normalizeChatMessage,\r\n normalizeChatMessages,\r\n} from './core/message-schema'\r\nexport { ChatOutbox, MemoryChatOutboxStorage } from './core/outbox'\r\nexport type {\r\n ChatOutboxEntry,\r\n ChatOutboxFlushOptions,\r\n ChatOutboxFlushResult,\r\n ChatOutboxOptions,\r\n ChatOutboxStorage,\r\n} from './core/outbox'\r\nexport { ChatTransportController } from './core/transport'\r\nexport type {\r\n ChatTransport,\r\n ChatTransportAck,\r\n ChatTransportContext,\r\n ChatTransportControllerOptions,\r\n ChatTransportEvent,\r\n ChatTransportStatus,\r\n} from './core/transport'\r\n\r\n// Renderer\r\nexport { DOMRenderer } from './renderer/dom-renderer'\r\nexport {\r\n cls,\r\n clsx,\r\n injectStyles,\r\n removeStyles,\r\n updateStyles,\r\n} from './renderer/style-manager'\r\n// Theme\r\nexport { ThemeManager } from './theme/theme-manager'\r\n\r\nexport type { ThemeTokens } from './theme/tokens'\r\nexport { darkTokens, lightTokens } from './theme/tokens'\r\n// Types\r\nexport * from './types'\r\n\r\n/**\r\n * 创建聊天实例\r\n */\r\nexport function createChat(config: ChatConfig): ChatInstance {\r\n // 解析容器\r\n let container: HTMLElement | null\r\n if (typeof config.container === 'string') {\r\n if (typeof document === 'undefined') {\r\n throw new Error(\r\n '[Chat] A browser Document is required to resolve a container selector.'\r\n )\r\n }\r\n container = document.querySelector<HTMLElement>(config.container)\r\n } else {\r\n container = config.container\r\n }\r\n\r\n if (!container) {\r\n throw new Error(`[Chat] Container not found: ${config.container}`)\r\n }\r\n\r\n const ownerDocument = container.ownerDocument\r\n const prefix = normalizeClassPrefix(\r\n config.classPrefix ?? DEFAULT_CLASS_PREFIX\r\n )\r\n const normalizedConfig = {\r\n ...config,\r\n classPrefix: prefix,\r\n }\r\n const emitter = new EventEmitter()\r\n const chatManager = new ChatManager(emitter, normalizedConfig.messages)\r\n const mentionEngine = new MentionEngine(\r\n emitter,\r\n normalizedConfig.mentionMembers\r\n )\r\n const themeManager = new ThemeManager(\r\n emitter,\r\n normalizedConfig.theme ?? 'light',\r\n ownerDocument.defaultView\r\n )\r\n const renderer = new DOMRenderer(\r\n container,\r\n normalizedConfig,\r\n emitter,\r\n mentionEngine\r\n )\r\n let destroyed = false\r\n const schedule = (callback: () => void) => {\r\n const run = () => {\r\n if (!destroyed) callback()\r\n }\r\n if (ownerDocument.defaultView?.requestAnimationFrame) {\r\n ownerDocument.defaultView.requestAnimationFrame(run)\r\n } else {\r\n setTimeout(run, 0)\r\n }\r\n }\r\n\r\n // 初始化渲染\r\n renderer.init()\r\n renderer.renderMessages(chatManager.getMessages())\r\n renderer.setThemeTokens(themeManager.getTokens())\r\n injectStyles(themeManager.getTokens(), prefix, renderer.getRootElement())\r\n\r\n const applyTransportAck = async (ack: ChatTransportAck): Promise<void> => {\r\n const localId = chatManager.getMessageIdByClientMessageId(\r\n ack.clientMessageId\r\n )\r\n if (localId) {\r\n chatManager.updateMessage(localId, {\r\n ...(ack.message ?? {}),\r\n id: localId,\r\n clientMessageId: ack.clientMessageId,\r\n status: 'sent',\r\n ...(ack.sequence !== undefined && { sequence: ack.sequence }),\r\n ...(ack.cursor !== undefined && { cursor: ack.cursor }),\r\n })\r\n }\r\n if (normalizedConfig.outbox) {\r\n await normalizedConfig.outbox.remove(ack.clientMessageId)\r\n }\r\n emitter.emit('transport-ack', ack)\r\n }\r\n\r\n const handleTransportEvent = (event: ChatTransportEvent): void => {\r\n if (event.type === 'message') {\r\n chatManager.upsertMessage(\r\n {\r\n ...event.message,\r\n ...(event.cursor !== undefined && { cursor: event.cursor }),\r\n },\r\n { sequence: event.sequence, source: 'remote' }\r\n )\r\n } else if (event.type === 'ack') {\r\n void applyTransportAck(event.ack).catch(error => {\r\n emitter.emit('transport-error', error)\r\n })\r\n } else if (event.type === 'cursor') {\r\n emitter.emit('transport-cursor', event.cursor)\r\n } else {\r\n emitter.emit('transport-error', event.error, event.recoverable)\r\n }\r\n }\r\n\r\n const transportController = normalizedConfig.transport\r\n ? new ChatTransportController(normalizedConfig.transport, {\r\n conversationId: normalizedConfig.conversationId,\r\n cursor: normalizedConfig.transportCursor,\r\n onEvent: handleTransportEvent,\r\n onStatusChange: status => {\r\n emitter.emit('transport-status', status)\r\n },\r\n })\r\n : null\r\n\r\n // 初始滚动到底部\r\n schedule(() => {\r\n renderer.scrollToBottom(false)\r\n })\r\n\r\n // 监听主题变化\r\n emitter.on('theme-change', (_resolved: string, tokens: ThemeTokens) => {\r\n renderer.setThemeTokens(tokens)\r\n })\r\n\r\n // 监听消息变化\r\n emitter.on('message-added', (message: ChatMessage) => {\r\n renderer.appendMessage(message)\r\n schedule(() => {\r\n renderer.scrollToBottom(true)\r\n })\r\n })\r\n\r\n emitter.on('mention-select', (member: MentionItem) => {\r\n normalizedConfig.onMentionSelect?.(member)\r\n })\r\n\r\n emitter.on('messages-prepended', (messages: ChatMessage[]) => {\r\n renderer.prependMessages(messages)\r\n })\r\n\r\n emitter.on('message-updated', (message: ChatMessage) => {\r\n renderer.updateMessage(message.id, message)\r\n })\r\n\r\n emitter.on('message-removed', (message: ChatMessage) => {\r\n renderer.removeMessage(message.id)\r\n })\r\n\r\n // 流式消息内容追加\r\n emitter.on('message-content-appended', (id: string, content: string) => {\r\n renderer.updateMessageContent(id, content)\r\n schedule(() => {\r\n renderer.scrollToBottom(false)\r\n })\r\n })\r\n\r\n // 创建实例\r\n const instance: ChatInstance = {\r\n addMessage(message: ChatMessage) {\r\n if (!destroyed) chatManager.addMessage(message)\r\n },\r\n\r\n prependMessages(messages: ChatMessage[]) {\r\n if (!destroyed) chatManager.prependMessages(messages)\r\n },\r\n\r\n updateMessage(id: string, updates: Partial<ChatMessage>) {\r\n if (!destroyed) chatManager.updateMessage(id, updates)\r\n },\r\n\r\n removeMessage(id: string) {\r\n if (!destroyed) chatManager.removeMessage(id)\r\n },\r\n\r\n setMessages(messages: ChatMessage[]) {\r\n if (destroyed) return\r\n chatManager.setMessages(messages)\r\n renderer.renderMessages(chatManager.getMessages())\r\n schedule(() => {\r\n renderer.scrollToBottom(false)\r\n })\r\n },\r\n\r\n clearMessages() {\r\n if (!destroyed) {\r\n chatManager.clearMessages()\r\n renderer.renderMessages([])\r\n }\r\n },\r\n\r\n scrollToBottom(smooth = true) {\r\n if (!destroyed) renderer.scrollToBottom(smooth)\r\n },\r\n\r\n setTheme(theme: ThemeMode) {\r\n if (!destroyed) themeManager.setTheme(theme)\r\n },\r\n\r\n setMentionMembers(members: MentionItem[]) {\r\n if (!destroyed) mentionEngine.setMembers(members)\r\n },\r\n\r\n setLoadingMore(loading: boolean) {\r\n if (!destroyed) renderer.setLoadingMore(loading)\r\n },\r\n\r\n focusInput() {\r\n if (!destroyed) renderer.focusInput()\r\n },\r\n\r\n setInputContent(content: string) {\r\n if (!destroyed) renderer.setInputContent(content)\r\n },\r\n\r\n getInputContent() {\r\n return destroyed ? '' : renderer.getInputContent()\r\n },\r\n\r\n clearInput() {\r\n if (!destroyed) renderer.clearInput()\r\n },\r\n\r\n isAtBottom(threshold?: number) {\r\n return destroyed || renderer.isAtBottom(threshold)\r\n },\r\n\r\n on(event: string, handler: (...args: unknown[]) => void) {\r\n return destroyed ? () => {} : emitter.on(event, handler)\r\n },\r\n\r\n getMessages() {\r\n return destroyed ? [] : chatManager.getMessages()\r\n },\r\n\r\n getMessage(id: string) {\r\n return destroyed ? undefined : chatManager.getMessage(id)\r\n },\r\n\r\n appendMessageContent(id: string, chunk: string) {\r\n return destroyed ? false : chatManager.appendMessageContent(id, chunk)\r\n },\r\n\r\n finishStreaming(id: string, generation?: string) {\r\n return destroyed ? false : chatManager.finishStreaming(id, generation)\r\n },\r\n\r\n beginStreaming(id: string, generation?: string) {\r\n return destroyed ? null : chatManager.beginStreaming(id, generation)\r\n },\r\n\r\n cancelStreaming(id: string, generation?: string) {\r\n return destroyed ? false : chatManager.cancelStreaming(id, generation)\r\n },\r\n\r\n mergeMessage(message: ChatMessage, sequence?: number) {\r\n return destroyed\r\n ? 'ignored'\r\n : chatManager.upsertMessage(message, {\r\n sequence,\r\n source: 'remote',\r\n })\r\n },\r\n\r\n async connectTransport(signal?: AbortSignal) {\r\n if (!transportController) {\r\n throw new Error('No chat transport is configured.')\r\n }\r\n await transportController.connect(signal)\r\n },\r\n\r\n async disconnectTransport() {\r\n await transportController?.disconnect()\r\n },\r\n\r\n getTransportStatus(): ChatTransportStatus {\r\n return transportController?.getStatus() ?? 'idle'\r\n },\r\n\r\n async sendMessage(\r\n message: ChatMessage,\r\n options: { signal?: AbortSignal } = {}\r\n ): Promise<ChatTransportAck | void> {\r\n if (!transportController) {\r\n throw new Error('No chat transport is configured.')\r\n }\r\n if (destroyed) throw new Error('Chat instance is destroyed.')\r\n const prepared = normalizeChatMessage({\r\n ...message,\r\n clientMessageId:\r\n message.clientMessageId ?? createClientMessageId(message.id),\r\n status: message.status ?? 'sending',\r\n })\r\n chatManager.addMessage(prepared)\r\n try {\r\n if (normalizedConfig.outbox) {\r\n await normalizedConfig.outbox.enqueue(prepared)\r\n }\r\n const ack = await transportController.send(prepared, {\r\n signal: options.signal,\r\n clientMessageId: prepared.clientMessageId,\r\n })\r\n if (ack) await applyTransportAck(ack)\r\n else chatManager.markMessageStatus(prepared.id, 'sent')\r\n emitter.emit('message-sent', prepared, ack)\r\n return ack\r\n } catch (error) {\r\n chatManager.markMessageStatus(prepared.id, 'failed')\r\n emitter.emit('message-send-failed', prepared, error)\r\n throw error\r\n }\r\n },\r\n\r\n async flushOutbox(options: ChatOutboxFlushOptions = {}) {\r\n if (!normalizedConfig.outbox) {\r\n return { sent: [], failed: [], remaining: [] }\r\n }\r\n if (!transportController) {\r\n throw new Error('No chat transport is configured.')\r\n }\r\n return normalizedConfig.outbox.flush(async (message, sendOptions) => {\r\n const ack = await transportController.send(message, sendOptions)\r\n if (ack) await applyTransportAck(ack)\r\n else if (message.id) chatManager.markMessageStatus(message.id, 'sent')\r\n }, options)\r\n },\r\n\r\n destroy() {\r\n if (destroyed) return\r\n destroyed = true\r\n transportController?.dispose()\r\n themeManager.destroy()\r\n renderer.destroy()\r\n emitter.removeAll()\r\n removeStyles(prefix, ownerDocument)\r\n },\r\n }\r\n\r\n if (normalizedConfig.autoConnect && transportController) {\r\n void instance.connectTransport().catch(error => {\r\n emitter.emit('transport-error', error)\r\n })\r\n }\r\n\r\n return instance\r\n}\r\n\r\nfunction createClientMessageId(messageId: string): string {\r\n const cryptoObject = globalThis.crypto\r\n if (cryptoObject?.randomUUID) return cryptoObject.randomUUID()\r\n return `client-${messageId}-${Date.now()}-${Math.random().toString(36).slice(2)}`\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":1,"configuration":"145717386b4d2d128af738e9fd91da86fa87eb965d5b0ac9e9e1d02fac495d85","sources":{"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\constants\\dom.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\constants\\dom.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\core\\transport.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\core\\transport.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\core\\message-schema.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\core\\message-schema.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\core\\outbox.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\core\\outbox.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\types\\index.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\types\\index.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\core\\event-emitter.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\core\\event-emitter.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\core\\chat-manager.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\core\\chat-manager.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\core\\mention-engine.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\core\\mention-engine.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\theme\\tokens.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\theme\\tokens.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\renderer\\style-manager.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\renderer\\style-manager.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\renderer\\dom-renderer.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\renderer\\dom-renderer.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\theme\\theme-manager.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\theme\\theme-manager.d.ts"],"D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\src\\index.ts":["D:\\WorkBench\\ldesign\\libraries\\chat\\packages\\core\\es\\index.d.ts"]}}
@@ -0,0 +1 @@
1
+ {"fileNames":["../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.scripthost.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.full.d.ts","../src/constants/dom.ts","../src/core/transport.ts","../src/core/message-schema.ts","../src/core/outbox.ts","../src/types/index.ts","../src/core/event-emitter.ts","../src/core/chat-manager.ts","../src/core/mention-engine.ts","../src/theme/tokens.ts","../src/renderer/style-manager.ts","../src/renderer/dom-renderer.ts","../src/theme/theme-manager.ts","../src/index.ts"],"fileIdsList":[[54,56,57],[56,57],[56],[54,56],[52,53,54,55,56,57,58,59,60,61,62,63],[52,56,57,59,60,61],[52,60],[56,57,60],[53,55]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"1305d1e76ca44e30fb8b2b8075fa522b83f60c0bcf5d4326a9d2cf79b53724f8","impliedFormat":1},{"version":"ba3b8d98781984d365e450f422f751087bf44b58d4f84d1f4c32a42bc309f201","signature":"5c30633c1ba767e2d63f9ee27a0af552e741db6e6e1c654168776b18a5ed9e5f"},{"version":"412ea23191cdd7ea78f3f5e663aeef54502a2262e40458fa8d7790b21a4840b9","signature":"b14c48055407bf3b21426f99398495e005bcbe5b20e502de3d977679388ff24d"},{"version":"1aa4cc48e4628a352bf4cc6b19a924925718ab74ce296bad34256a4a28e099e9","signature":"fc1c53b984f15f8b8a468a7df6cc1fd57af734a846c988787dd170fda86a2d42"},{"version":"24f4f42bfb981d928e19fd8d1bb48e13f0740eed4e50c74fffc5c892e5599ee1","signature":"1ef9e71ed3e37b16295a9e9730f9c742041c7ab0733a6f179646d8bf4927a61a"},{"version":"0b51b019120d49e1e9369e2fab31ac9ee1b1f3f7654f65e9ff06c2302f78158f","signature":"e6259070ee43d8cbfc95d976ac43f7f2903ffe7e3954225bea1f84845f7475ee"},{"version":"414d09e17d2678763e1d533fc2fa3bad35d07638bd6fe4c0a9248463481ce7e4","signature":"1cfe66ce070a1e020279ca6c1b461b3d342de94dc9d2177de53a05548c9afdcd"},{"version":"b0d92d2f2ca004d8c1205fde8b10d2552ec67fa11d1f6c8fcf184b170278f9b1","signature":"877d2b4eaea9051cb20ca69cd95b5613e7d742ae62aab5926adf1cf0a38438f2"},{"version":"df99573db3ed11286dd41a78c86d08aa095bb5e2d5b6e7fa2c07fe0fc5d92fc3","signature":"05c1cb3c29e1fb03e193b0d4a8558e6a1b5fac067a560fd36b0224c06d8b8901"},{"version":"c2032e68cb40bba54426eba446651a72a5d2693b2061f2569d41c6089ae61993","signature":"82e9485b789ce533304effae3d5337b38d713a35d0b6e44db664e773acced9c9"},{"version":"80644b3ea8cfd3533c892900a23f18a373c57721acc9829d29505d945909b6b8","signature":"dda7123af2863af6dd0fd8f75f01cfeddd038d81b7632b6e67a0639822059965"},{"version":"3034870239a0edebffe691e3030115d83fbbb01863bab37c22975cd979567a03","signature":"1b2e0f746d5f04ee0f8d4122dfc3e880a75e1ae4fdc2bf7eb9d255bad569bdde"},{"version":"417da194a0cff87a605c1db6714fac9fdf41a35aac533587791d1a758c4de258","signature":"1debc7be32e2b65364f18c97634289a67c3f0a749978672bff4740ce72dd20e6"},{"version":"6a01eb3706106fb49b302a495349201516bcc29eae315081303e352f49aced7c","signature":"854bdabe5110cd8e6547bbb059a863eed1041499f854d699d359436e4fd23582"}],"root":[[52,64]],"options":{"allowJs":false,"declaration":true,"declarationDir":"./","declarationMap":false,"emitDeclarationOnly":true,"esModuleInterop":true,"module":99,"noImplicitAny":false,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":false,"target":7,"tsBuildInfoFile":"./.dts.tsbuildinfo"},"referencedMap":[[58,1],[59,2],[54,3],[55,4],[53,3],[64,5],[62,6],[61,7],[63,8],[56,9]],"semanticDiagnosticsPerFile":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64],"version":"5.9.3"}
@@ -5,37 +5,21 @@
5
5
  export declare const DEFAULT_CLASS_PREFIX = "ldesign-chat";
6
6
  export declare const COMPONENT_CSS_VAR_PREFIX = "--ldesign-chat";
7
7
  export declare const STYLE_ELEMENT_ID = "ldesign-chat-styles";
8
- /**
9
- * normalizeClassPrefix 函数
10
- * @param prefix? - 参数
11
- * @returns 返回值
12
- */
13
8
  /**
14
9
  * normalizeClassPrefix - normalize Class Prefix function
15
- * @param prefix? - 参数说明
10
+ * @param prefix - Optional class prefix
16
11
  * @returns 返回值说明
17
12
  */
18
13
  export declare function normalizeClassPrefix(prefix?: string): string;
19
- /**
20
- * getStyleElementId 函数
21
- * @param prefix = DEFAULT_CLASS_PREFIX - 参数
22
- * @returns 返回值
23
- */
24
14
  /**
25
15
  * getStyleElementId - get Style Element Id function
26
- * @param prefix = DEFAULT_CLASS_PREFIX - 参数说明
16
+ * @param prefix - Class prefix
27
17
  * @returns 返回值说明
28
18
  */
29
19
  export declare function getStyleElementId(prefix?: string): string;
30
- /**
31
- * cx 函数
32
- * @param ...classes - 参数
33
- * @returns 返回值
34
- */
35
20
  /**
36
21
  * cx - cx function
37
- * @param ...classes - 参数说明
22
+ * @param classes - Class names to join
38
23
  * @returns 返回值说明
39
24
  */
40
25
  export declare function cx(...classes: (string | false | null | undefined)[]): string;
41
- //# sourceMappingURL=dom.d.ts.map