@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.
- package/README.md +187 -123
- package/dist/index.js +2018 -1035
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1370 -1644
- package/dist/index.min.js.map +1 -0
- package/es/.dts-output-manifest.json +1 -0
- package/es/.dts.tsbuildinfo +1 -0
- package/es/constants/dom.d.ts +3 -19
- package/es/constants/dom.js +4 -4
- package/es/constants/dom.js.map +1 -1
- package/es/core/chat-manager.d.ts +33 -22
- package/es/core/chat-manager.js +174 -50
- package/es/core/chat-manager.js.map +1 -1
- package/es/core/event-emitter.d.ts +0 -1
- package/es/core/event-emitter.js +14 -7
- package/es/core/event-emitter.js.map +1 -1
- package/es/core/mention-engine.d.ts +1 -2
- package/es/core/mention-engine.js +9 -9
- package/es/core/mention-engine.js.map +1 -1
- package/es/core/message-schema.d.ts +19 -0
- package/es/core/message-schema.js +197 -0
- package/es/core/message-schema.js.map +1 -0
- package/es/core/outbox.d.ts +63 -0
- package/es/core/outbox.js +160 -0
- package/es/core/outbox.js.map +1 -0
- package/es/core/transport.d.ts +79 -0
- package/es/core/transport.js +102 -0
- package/es/core/transport.js.map +1 -0
- package/es/index.d.ts +12 -7
- package/es/index.js +167 -36
- package/es/index.js.map +1 -1
- package/es/renderer/dom-renderer.d.ts +16 -4
- package/es/renderer/dom-renderer.js +316 -61
- package/es/renderer/dom-renderer.js.map +1 -1
- package/es/renderer/style-manager.d.ts +14 -38
- package/es/renderer/style-manager.js +92 -63
- package/es/renderer/style-manager.js.map +1 -1
- package/es/theme/theme-manager.d.ts +4 -3
- package/es/theme/theme-manager.js +19 -9
- package/es/theme/theme-manager.js.map +1 -1
- package/es/theme/tokens.d.ts +0 -1
- package/es/theme/tokens.js +92 -92
- package/es/theme/tokens.js.map +1 -1
- package/es/types/index.d.ts +104 -24
- package/es/types/index.js +8 -3
- package/es/types/index.js.map +1 -0
- package/esm/constants/dom.d.ts +3 -19
- package/esm/constants/dom.js +4 -4
- package/esm/constants/dom.js.map +1 -1
- package/esm/core/chat-manager.d.ts +33 -22
- package/esm/core/chat-manager.js +174 -50
- package/esm/core/chat-manager.js.map +1 -1
- package/esm/core/event-emitter.d.ts +0 -1
- package/esm/core/event-emitter.js +14 -7
- package/esm/core/event-emitter.js.map +1 -1
- package/esm/core/mention-engine.d.ts +1 -2
- package/esm/core/mention-engine.js +9 -9
- package/esm/core/mention-engine.js.map +1 -1
- package/esm/core/message-schema.d.ts +19 -0
- package/esm/core/message-schema.js +197 -0
- package/esm/core/message-schema.js.map +1 -0
- package/esm/core/outbox.d.ts +63 -0
- package/esm/core/outbox.js +160 -0
- package/esm/core/outbox.js.map +1 -0
- package/esm/core/transport.d.ts +79 -0
- package/esm/core/transport.js +102 -0
- package/esm/core/transport.js.map +1 -0
- package/esm/index.d.ts +12 -7
- package/esm/index.js +169 -38
- package/esm/index.js.map +1 -1
- package/esm/renderer/dom-renderer.d.ts +16 -4
- package/esm/renderer/dom-renderer.js +316 -61
- package/esm/renderer/dom-renderer.js.map +1 -1
- package/esm/renderer/style-manager.d.ts +14 -38
- package/esm/renderer/style-manager.js +92 -63
- package/esm/renderer/style-manager.js.map +1 -1
- package/esm/theme/theme-manager.d.ts +4 -3
- package/esm/theme/theme-manager.js +19 -9
- package/esm/theme/theme-manager.js.map +1 -1
- package/esm/theme/tokens.d.ts +0 -1
- package/esm/theme/tokens.js +92 -92
- package/esm/theme/tokens.js.map +1 -1
- package/esm/types/index.d.ts +104 -24
- package/esm/types/index.js +8 -3
- package/esm/types/index.js.map +1 -0
- package/lib/constants/dom.cjs +4 -4
- package/lib/constants/dom.cjs.map +1 -1
- package/lib/constants/dom.d.cts +25 -0
- package/lib/constants/dom.d.ts +3 -19
- package/lib/core/chat-manager.cjs +174 -50
- package/lib/core/chat-manager.cjs.map +1 -1
- package/lib/core/chat-manager.d.cts +45 -0
- package/lib/core/chat-manager.d.ts +33 -22
- package/lib/core/event-emitter.cjs +14 -7
- package/lib/core/event-emitter.cjs.map +1 -1
- package/lib/core/event-emitter.d.cts +47 -0
- package/lib/core/event-emitter.d.ts +0 -1
- package/lib/core/mention-engine.cjs +9 -9
- package/lib/core/mention-engine.cjs.map +1 -1
- package/lib/core/mention-engine.d.cts +40 -0
- package/lib/core/mention-engine.d.ts +1 -2
- package/lib/core/message-schema.cjs +202 -0
- package/lib/core/message-schema.cjs.map +1 -0
- package/lib/core/message-schema.d.cts +19 -0
- package/lib/core/message-schema.d.ts +19 -0
- package/lib/core/outbox.cjs +162 -0
- package/lib/core/outbox.cjs.map +1 -0
- package/lib/core/outbox.d.cts +63 -0
- package/lib/core/outbox.d.ts +63 -0
- package/lib/core/transport.cjs +103 -0
- package/lib/core/transport.cjs.map +1 -0
- package/lib/core/transport.d.cts +79 -0
- package/lib/core/transport.d.ts +79 -0
- package/lib/index.cjs +175 -35
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +33 -0
- package/lib/index.d.ts +12 -7
- package/lib/renderer/dom-renderer.cjs +316 -61
- package/lib/renderer/dom-renderer.cjs.map +1 -1
- package/lib/renderer/dom-renderer.d.cts +91 -0
- package/lib/renderer/dom-renderer.d.ts +16 -4
- package/lib/renderer/style-manager.cjs +92 -62
- package/lib/renderer/style-manager.cjs.map +1 -1
- package/lib/renderer/style-manager.d.cts +34 -0
- package/lib/renderer/style-manager.d.ts +14 -38
- package/lib/theme/theme-manager.cjs +19 -9
- package/lib/theme/theme-manager.cjs.map +1 -1
- package/lib/theme/theme-manager.d.cts +34 -0
- package/lib/theme/theme-manager.d.ts +4 -3
- package/lib/theme/tokens.cjs +92 -92
- package/lib/theme/tokens.cjs.map +1 -1
- package/lib/theme/tokens.d.cts +56 -0
- package/lib/theme/tokens.d.ts +0 -1
- package/lib/types/index.cjs +8 -3
- package/lib/types/index.cjs.map +1 -0
- package/lib/types/index.d.cts +284 -0
- package/lib/types/index.d.ts +104 -24
- package/package.json +16 -13
- package/es/constants/dom.d.ts.map +0 -1
- package/es/core/chat-manager.d.ts.map +0 -1
- package/es/core/event-emitter.d.ts.map +0 -1
- package/es/core/mention-engine.d.ts.map +0 -1
- package/es/index.d.ts.map +0 -1
- package/es/renderer/dom-renderer.d.ts.map +0 -1
- package/es/renderer/style-manager.d.ts.map +0 -1
- package/es/theme/theme-manager.d.ts.map +0 -1
- package/es/theme/tokens.d.ts.map +0 -1
- package/es/types/index.d.ts.map +0 -1
- package/esm/constants/dom.d.ts.map +0 -1
- package/esm/core/chat-manager.d.ts.map +0 -1
- package/esm/core/event-emitter.d.ts.map +0 -1
- package/esm/core/mention-engine.d.ts.map +0 -1
- package/esm/index.d.ts.map +0 -1
- package/esm/renderer/dom-renderer.d.ts.map +0 -1
- package/esm/renderer/style-manager.d.ts.map +0 -1
- package/esm/theme/theme-manager.d.ts.map +0 -1
- package/esm/theme/tokens.d.ts.map +0 -1
- package/esm/types/index.d.ts.map +0 -1
- package/lib/constants/dom.d.ts.map +0 -1
- package/lib/core/chat-manager.d.ts.map +0 -1
- package/lib/core/event-emitter.d.ts.map +0 -1
- package/lib/core/mention-engine.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/renderer/dom-renderer.d.ts.map +0 -1
- package/lib/renderer/style-manager.d.ts.map +0 -1
- package/lib/theme/theme-manager.d.ts.map +0 -1
- package/lib/theme/tokens.d.ts.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["row"],"sources":["../src/core/event-emitter.ts","../src/core/chat-manager.ts","../src/core/mention-engine.ts","../src/theme/tokens.ts","../src/theme/theme-manager.ts","../src/constants/dom.ts","../src/renderer/dom-renderer.ts","../src/renderer/style-manager.ts","../src/index.ts"],"sourcesContent":["/**\n * 轻量事件总线\n * 提供发布/订阅模式的事件管理功能,支持事件的注册、注销、触发等操作\n */\n\n// 定义事件处理函数的类型签名:接收任意数量的未知类型参数,无返回值\ntype Handler = (...args: unknown[]) => void;\n\n/**\n * EventEmitter - 事件发射器类\n * 实现了经典的发布/订阅(Pub/Sub)模式,用于模块间的解耦通信\n * 支持:一次性监听、批量移除、自动清理等功能\n */\nexport class EventEmitter {\n // 使用 Map 存储事件名到处理函数集合的映射关系\n // 键为事件名称(字符串),值为该事件对应的处理函数 Set 集合\n // 使用 Set 而非数组,可自动去重同一处理函数的重复注册\n private listeners = new Map<string, Set<Handler>>();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param handler - 事件触发时执行的回调函数\n * @returns 返回一个取消订阅的函数,调用即可移除该监听器\n */\n on(event: string, handler: Handler): () => void {\n // 如果该事件还没有任何监听器,则创建一个新的 Set 集合\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n // 将处理函数添加到该事件的监听器集合中\n // 使用非空断言(!)因为上方已确认该事件集合存在\n this.listeners.get(event)!.add(handler);\n // 返回一个取消订阅函数,方便调用者链式调用后自行移除\n return () => this.off(event, handler);\n }\n\n /**\n * 移除指定事件的某个监听器\n * @param event - 事件名称\n * @param handler - 要移除的处理函数引用(必须与注册时为同一函数引用)\n */\n off(event: string, handler: Handler): void {\n // 可选链调用:如果该事件存在监听器集合,则从中删除指定处理函数\n // 若事件不存在则安全跳过,不会抛出异常\n this.listeners.get(event)?.delete(handler);\n }\n\n /**\n * 触发(发射)指定事件,依次调用所有已注册的监听器\n * @param event - 要触发的事件名称\n * @param args - 传递给监听器函数的参数列表(剩余参数语法)\n */\n emit(event: string, ...args: unknown[]): void {\n // 获取该事件的监听器集合,若存在则遍历调用每个处理函数\n this.listeners.get(event)?.forEach((handler) => {\n try {\n // 使用展开运算符将参数数组传递给处理函数\n handler(...args);\n } catch (err) {\n // 捕获单个处理函数的异常,避免影响其他监听器的执行\n // 同时输出错误日志便于调试,标注所属模块为 [Chat]\n console.error(`[Chat] Event handler error for \"${event}\":`, err);\n }\n });\n }\n\n /**\n * 注册一次性事件监听器(触发一次后自动移除)\n * @param event - 要监听的事件名称\n * @param handler - 事件触发时执行的回调函数\n * @returns 返回取消订阅的函数,可在触发前手动取消\n */\n once(event: string, handler: Handler): () => void {\n // 创建包装函数:先移除自身,再调用原始处理函数\n // 这样保证该监听器只执行一次\n const wrapper = (...args: unknown[]) => {\n // 先从事件中移除包装函数自身,防止重复触发\n this.off(event, wrapper);\n // 再执行用户注册的原始处理函数\n handler(...args);\n };\n // 将包装函数注册为普通监听器,复用 on() 的逻辑\n return this.on(event, wrapper);\n }\n\n /**\n * 批量移除事件监听器\n * @param event - 可选的事件名称\n * - 若传入事件名,则只移除该事件的所有监听器\n * - 若不传参数,则清空所有事件的所有监听器\n */\n removeAll(event?: string): void {\n if (event) {\n // 移除指定事件的全部监听器(直接删除整个事件条目)\n this.listeners.delete(event);\n } else {\n // 不传参数时,清空整个监听器映射表,移除所有事件\n this.listeners.clear();\n }\n }\n}\n","/**\n * 聊天管理器 - 消息增删改查、状态管理\n */\n\nimport type { ChatMessage } from '../types';\nimport { EventEmitter } from './event-emitter';\n\n/**\n * ChatManager - Chat Manager class\n */\nexport class ChatManager {\n private messages: ChatMessage[] = [];\n private emitter: EventEmitter;\n\n constructor(emitter: EventEmitter, initialMessages?: ChatMessage[]) {\n this.emitter = emitter;\n if (initialMessages?.length) {\n this.messages = [...initialMessages];\n }\n }\n\n /** 获取所有消息 */\n getMessages(): ChatMessage[] {\n return [...this.messages];\n }\n\n /** 根据 ID 获取消息 */\n getMessage(id: string): ChatMessage | undefined {\n return this.messages.find((m) => m.id === id);\n }\n\n /** 添加消息(末尾追加) */\n addMessage(message: ChatMessage): void {\n this.messages.push(message);\n this.emitter.emit('message-added', message);\n this.emitter.emit('messages-changed', this.getMessages());\n }\n\n /** 在顶部批量插入消息(用于加载更多) */\n prependMessages(messages: ChatMessage[]): void {\n this.messages.unshift(...messages);\n this.emitter.emit('messages-prepended', messages);\n this.emitter.emit('messages-changed', this.getMessages());\n }\n\n /** 更新消息 */\n updateMessage(id: string, updates: Partial<ChatMessage>): void {\n const index = this.messages.findIndex((m) => m.id === id);\n if (index === -1) return;\n\n this.messages[index] = { ...this.messages[index], ...updates };\n this.emitter.emit('message-updated', this.messages[index]);\n this.emitter.emit('messages-changed', this.getMessages());\n }\n\n /** 删除消息 */\n removeMessage(id: string): void {\n const index = this.messages.findIndex((m) => m.id === id);\n if (index === -1) return;\n\n const removed = this.messages.splice(index, 1)[0];\n this.emitter.emit('message-removed', removed);\n this.emitter.emit('messages-changed', this.getMessages());\n }\n\n /** 替换全部消息 */\n setMessages(messages: ChatMessage[]): void {\n this.messages = [...messages];\n this.emitter.emit('messages-changed', this.getMessages());\n }\n\n /** 清空所有消息 */\n clearMessages(): void {\n this.messages = [];\n this.emitter.emit('messages-changed', []);\n }\n\n /** 追加流式消息内容 */\n appendMessageContent(id: string, chunk: string): void {\n const index = this.messages.findIndex((m) => m.id === id);\n if (index === -1) return;\n\n const msg = this.messages[index];\n this.messages[index] = {\n ...msg,\n content: (msg.content ?? '') + chunk,\n };\n this.emitter.emit('message-content-appended', id, this.messages[index].content);\n this.emitter.emit('messages-changed', this.getMessages());\n }\n\n /** 完成流式消息 */\n finishStreaming(id: string): void {\n const index = this.messages.findIndex((m) => m.id === id);\n if (index === -1) return;\n\n this.messages[index] = { ...this.messages[index], streaming: false };\n this.emitter.emit('message-updated', this.messages[index]);\n this.emitter.emit('messages-changed', this.getMessages());\n }\n}\n","/**\n * @file mention-engine.ts\n * @description mention-engine 模块\n */\n\nimport type { MentionItem } from '../types';\nimport { EventEmitter } from './event-emitter';\n\n/**\n * MentionState interface\n */\nexport interface MentionState {\n active: boolean;\n query: string;\n filtered: MentionItem[];\n activeIndex: number;\n triggerPosition: number;\n}\n\n/**\n * MentionEngine 类\n */\nexport class MentionEngine {\n private members: MentionItem[] = [];\n private emitter: EventEmitter;\n private state: MentionState = {\n active: false,\n query: '',\n filtered: [],\n activeIndex: 0,\n triggerPosition: -1,\n };\n private selectedMentions: MentionItem[] = [];\n\n constructor(emitter: EventEmitter, members?: MentionItem[]) {\n this.emitter = emitter;\n if (members) this.members = [...members];\n }\n\n getState(): MentionState {\n return {\n ...this.state,\n filtered: [...this.state.filtered],\n };\n }\n\n getSelectedMentions(): MentionItem[] {\n return [...this.selectedMentions];\n }\n\n setMembers(members: MentionItem[]): void {\n this.members = [...members];\n if (this.state.active) {\n this.filter(this.state.query);\n }\n }\n\n handleInput(text: string, cursorPos: number): void {\n const beforeCursor = text.slice(0, cursorPos);\n const atIndex = beforeCursor.lastIndexOf('@');\n\n if (atIndex === -1) {\n this.deactivate();\n return;\n }\n\n if (atIndex > 0 && !/\\s/.test(beforeCursor[atIndex - 1])) {\n this.deactivate();\n return;\n }\n\n const query = beforeCursor.slice(atIndex + 1);\n if (/[^\\S\\r\\n]/.test(query)) {\n this.deactivate();\n return;\n }\n\n this.state.active = true;\n this.state.triggerPosition = atIndex;\n this.filter(query);\n }\n\n moveUp(): void {\n if (!this.state.active || this.state.filtered.length === 0) return;\n this.state.activeIndex =\n (this.state.activeIndex - 1 + this.state.filtered.length) %\n this.state.filtered.length;\n this.emitter.emit('mention-active-change', this.state.activeIndex);\n }\n\n moveDown(): void {\n if (!this.state.active || this.state.filtered.length === 0) return;\n this.state.activeIndex =\n (this.state.activeIndex + 1) % this.state.filtered.length;\n this.emitter.emit('mention-active-change', this.state.activeIndex);\n }\n\n selectCurrent(): MentionItem | null {\n if (!this.state.active || this.state.filtered.length === 0) return null;\n return this.select(this.state.activeIndex);\n }\n\n select(index: number): MentionItem | null {\n if (index < 0 || index >= this.state.filtered.length) return null;\n const member = this.state.filtered[index];\n if (!this.selectedMentions.find((m) => m.id === member.id)) {\n this.selectedMentions.push(member);\n }\n this.emitter.emit('mention-select', member);\n this.deactivate();\n return member;\n }\n\n deactivate(): void {\n if (!this.state.active) return;\n this.state = {\n active: false,\n query: '',\n filtered: [],\n activeIndex: 0,\n triggerPosition: -1,\n };\n this.emitter.emit('mention-deactivate');\n }\n\n parseMentions(text: string): MentionItem[] {\n const mentions: MentionItem[] = [];\n const sortedMembers = [...this.members].sort((a, b) => b.name.length - a.name.length);\n\n for (const member of sortedMembers) {\n const pattern = new RegExp(`(^|\\\\s)@${this.escapeRegex(member.name)}(?=\\\\s|$|[,。!?,.!?])`, 'u');\n if (pattern.test(text) && !mentions.find((m) => m.id === member.id)) {\n mentions.push(member);\n }\n }\n\n return mentions;\n }\n\n resetSelected(): void {\n this.selectedMentions = [];\n }\n\n getInsertText(member: MentionItem): string {\n return `@${member.name} `;\n }\n\n private filter(query: string): void {\n const normalizedQuery = query.trim().toLowerCase();\n this.state.query = query;\n this.state.filtered = this.members.filter((member) =>\n member.name.toLowerCase().includes(normalizedQuery) ||\n member.id.toLowerCase().includes(normalizedQuery),\n );\n this.state.activeIndex = 0;\n this.emitter.emit('mention-filter', this.getState());\n }\n\n private escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n}\n","/**\n * @file tokens.ts\n * @description tokens 模块\n */\n\n/**\n * ThemeTokens interface\n */\nexport interface ThemeTokens {\n bgPrimary: string;\n bgSecondary: string;\n bgBubbleOutgoing: string;\n bgBubbleIncoming: string;\n bgInput: string;\n bgMention: string;\n bgMentionHover: string;\n bgMentionActive: string;\n bgLoadMore: string;\n bgSystemMessage: string;\n bgDropOverlay: string;\n bgDangerSoft: string;\n\n textPrimary: string;\n textSecondary: string;\n textBubbleOutgoing: string;\n textBubbleIncoming: string;\n textMention: string;\n textMentionTag: string;\n textTimestamp: string;\n textSystem: string;\n textPlaceholder: string;\n\n borderPrimary: string;\n borderInput: string;\n borderInputFocus: string;\n borderMention: string;\n\n colorSending: string;\n colorSent: string;\n colorDelivered: string;\n colorRead: string;\n colorFailed: string;\n colorLink: string;\n\n shadowPanel: string;\n shadowMention: string;\n\n avatarBg: string;\n avatarText: string;\n\n btnPrimaryBg: string;\n btnPrimaryText: string;\n btnPrimaryHover: string;\n\n scrollbarThumb: string;\n scrollbarTrack: string;\n\n bgToolbar: string;\n borderToolbar: string;\n toolbarIconColor: string;\n toolbarIconHover: string;\n toolbarVoiceActive: string;\n}\n\nexport const lightTokens: ThemeTokens = {\n bgPrimary: 'var(--color-gray-50)',\n bgSecondary: 'var(--color-gray-100)',\n bgBubbleOutgoing: 'var(--color-primary-default)',\n bgBubbleIncoming: 'var(--color-gray-100)',\n bgInput: 'var(--color-gray-50)',\n bgMention: 'var(--color-gray-50)',\n bgMentionHover: 'var(--color-primary-50)',\n bgMentionActive: 'var(--color-primary-100)',\n bgLoadMore: 'var(--color-gray-100)',\n bgSystemMessage: 'var(--color-gray-100)',\n bgDropOverlay: 'color-mix(in srgb, var(--color-primary-default) 10%, var(--color-gray-50))',\n bgDangerSoft: 'color-mix(in srgb, var(--color-danger-default) 12%, var(--color-gray-50))',\n\n textPrimary: 'var(--color-gray-900)',\n textSecondary: 'var(--color-gray-600)',\n textBubbleOutgoing: 'var(--color-gray-50)',\n textBubbleIncoming: 'var(--color-gray-900)',\n textMention: 'var(--color-gray-900)',\n textMentionTag: 'var(--color-primary-default)',\n textTimestamp: 'var(--color-gray-500)',\n textSystem: 'var(--color-gray-600)',\n textPlaceholder: 'var(--color-gray-400)',\n\n borderPrimary: 'var(--color-gray-200)',\n borderInput: 'var(--color-gray-300)',\n borderInputFocus: 'var(--color-primary-default)',\n borderMention: 'var(--color-gray-200)',\n\n colorSending: 'var(--color-gray-400)',\n colorSent: 'var(--color-gray-500)',\n colorDelivered: 'var(--color-primary-default)',\n colorRead: 'var(--color-success-default)',\n colorFailed: 'var(--color-danger-default)',\n colorLink: 'var(--color-primary-default)',\n\n shadowPanel: 'var(--size-shadow-2)',\n shadowMention: 'var(--size-shadow-4)',\n\n avatarBg: 'var(--color-primary-default)',\n avatarText: 'var(--color-gray-50)',\n\n btnPrimaryBg: 'var(--color-primary-default)',\n btnPrimaryText: 'var(--color-gray-50)',\n btnPrimaryHover: 'var(--color-primary-hover)',\n\n scrollbarThumb: 'var(--color-gray-300)',\n scrollbarTrack: 'var(--color-gray-100)',\n\n bgToolbar: 'var(--color-gray-100)',\n borderToolbar: 'var(--color-gray-200)',\n toolbarIconColor: 'var(--color-gray-600)',\n toolbarIconHover: 'var(--color-primary-default)',\n toolbarVoiceActive: 'var(--color-danger-default)',\n};\n\nexport const darkTokens: ThemeTokens = {\n bgPrimary: 'var(--color-gray-900)',\n bgSecondary: 'var(--color-gray-800)',\n bgBubbleOutgoing: 'var(--color-primary-default)',\n bgBubbleIncoming: 'var(--color-gray-800)',\n bgInput: 'var(--color-gray-900)',\n bgMention: 'var(--color-gray-900)',\n bgMentionHover: 'var(--color-gray-800)',\n bgMentionActive: 'var(--color-primary-900)',\n bgLoadMore: 'var(--color-gray-800)',\n bgSystemMessage: 'var(--color-gray-800)',\n bgDropOverlay: 'color-mix(in srgb, var(--color-primary-default) 16%, var(--color-gray-900))',\n bgDangerSoft: 'color-mix(in srgb, var(--color-danger-default) 18%, var(--color-gray-900))',\n\n textPrimary: 'var(--color-gray-50)',\n textSecondary: 'var(--color-gray-300)',\n textBubbleOutgoing: 'var(--color-gray-50)',\n textBubbleIncoming: 'var(--color-gray-50)',\n textMention: 'var(--color-gray-50)',\n textMentionTag: 'var(--color-primary-300)',\n textTimestamp: 'var(--color-gray-400)',\n textSystem: 'var(--color-gray-300)',\n textPlaceholder: 'var(--color-gray-500)',\n\n borderPrimary: 'var(--color-gray-700)',\n borderInput: 'var(--color-gray-700)',\n borderInputFocus: 'var(--color-primary-default)',\n borderMention: 'var(--color-gray-700)',\n\n colorSending: 'var(--color-gray-500)',\n colorSent: 'var(--color-gray-400)',\n colorDelivered: 'var(--color-primary-300)',\n colorRead: 'var(--color-success-default)',\n colorFailed: 'var(--color-danger-default)',\n colorLink: 'var(--color-primary-300)',\n\n shadowPanel: 'var(--size-shadow-3)',\n shadowMention: 'var(--size-shadow-6)',\n\n avatarBg: 'var(--color-primary-default)',\n avatarText: 'var(--color-gray-50)',\n\n btnPrimaryBg: 'var(--color-primary-default)',\n btnPrimaryText: 'var(--color-gray-50)',\n btnPrimaryHover: 'var(--color-primary-hover)',\n\n scrollbarThumb: 'var(--color-gray-700)',\n scrollbarTrack: 'var(--color-gray-800)',\n\n bgToolbar: 'var(--color-gray-800)',\n borderToolbar: 'var(--color-gray-700)',\n toolbarIconColor: 'var(--color-gray-300)',\n toolbarIconHover: 'var(--color-primary-300)',\n toolbarVoiceActive: 'var(--color-danger-default)',\n};\n","/**\n * 主题管理器\n */\n\nimport type { ThemeMode } from '../types';\nimport type { ThemeTokens } from './tokens';\nimport { lightTokens, darkTokens } from './tokens';\nimport { EventEmitter } from '../core/event-emitter';\n\n/**\n * ThemeManager - Theme Manager class\n */\nexport class ThemeManager {\n private mode: ThemeMode = 'light';\n private emitter: EventEmitter;\n private mediaQuery: MediaQueryList | null = null;\n private mediaHandler: ((e: MediaQueryListEvent) => void) | null = null;\n\n constructor(emitter: EventEmitter, mode?: ThemeMode) {\n this.emitter = emitter;\n if (mode) this.setTheme(mode);\n }\n\n /** 获取当前模式 */\n getMode(): ThemeMode {\n return this.mode;\n }\n\n /** 获取当前实际主题(auto 时解析为 light/dark) */\n getResolvedTheme(): 'light' | 'dark' {\n if (this.mode === 'auto') {\n return this.getSystemTheme();\n }\n return this.mode;\n }\n\n /** 获取当前主题令牌 */\n getTokens(): ThemeTokens {\n return this.getResolvedTheme() === 'dark' ? darkTokens : lightTokens;\n }\n\n /** 设置主题 */\n setTheme(mode: ThemeMode): void {\n this.cleanupMediaListener();\n this.mode = mode;\n\n if (mode === 'auto') {\n this.setupMediaListener();\n }\n\n this.emitter.emit('theme-change', this.getResolvedTheme(), this.getTokens());\n }\n\n /** 获取系统主题偏好 */\n private getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n /** 监听系统主题变化 */\n private setupMediaListener(): void {\n if (typeof window === 'undefined') return;\n this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n this.mediaHandler = () => {\n this.emitter.emit('theme-change', this.getResolvedTheme(), this.getTokens());\n };\n this.mediaQuery.addEventListener('change', this.mediaHandler);\n }\n\n /** 清理监听器 */\n private cleanupMediaListener(): void {\n if (this.mediaQuery && this.mediaHandler) {\n this.mediaQuery.removeEventListener('change', this.mediaHandler);\n this.mediaQuery = null;\n this.mediaHandler = null;\n }\n }\n\n /** 销毁 */\n destroy(): void {\n this.cleanupMediaListener();\n }\n}\n","/**\n * @file dom.ts\n * @description dom 模块\n */\n\nexport const DEFAULT_CLASS_PREFIX = 'ldesign-chat';\nexport const COMPONENT_CSS_VAR_PREFIX = '--ldesign-chat';\nexport const STYLE_ELEMENT_ID = 'ldesign-chat-styles';\n\n/**\n * normalizeClassPrefix 函数\n * @param prefix? - 参数\n * @returns 返回值\n */\n/**\n * normalizeClassPrefix - normalize Class Prefix function\n * @param prefix? - 参数说明\n * @returns 返回值说明\n */\nexport function normalizeClassPrefix(prefix?: string): string {\n const trimmed = prefix?.trim();\n if (!trimmed) return DEFAULT_CLASS_PREFIX;\n if (trimmed.startsWith('ldesign-')) return trimmed;\n return `ldesign-${trimmed.replace(/^-+/, '')}`;\n}\n\n/**\n * getStyleElementId 函数\n * @param prefix = DEFAULT_CLASS_PREFIX - 参数\n * @returns 返回值\n */\n/**\n * getStyleElementId - get Style Element Id function\n * @param prefix = DEFAULT_CLASS_PREFIX - 参数说明\n * @returns 返回值说明\n */\nexport function getStyleElementId(prefix = DEFAULT_CLASS_PREFIX): string {\n const normalized = normalizeClassPrefix(prefix);\n return normalized === DEFAULT_CLASS_PREFIX\n ? STYLE_ELEMENT_ID\n : `${normalized}-styles`;\n}\n\n/**\n * cx 函数\n * @param ...classes - 参数\n * @returns 返回值\n */\n/**\n * cx - cx function\n * @param ...classes - 参数说明\n * @returns 返回值说明\n */\nexport function cx(...classes: (string | false | null | undefined)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n","import type { ChatConfig, ChatMessage, MentionItem, MessageStatus } from '../types';\nimport { EventEmitter } from '../core/event-emitter';\nimport { MentionEngine } from '../core/mention-engine';\nimport { DEFAULT_CLASS_PREFIX, cx, normalizeClassPrefix } from '../constants/dom';\n\nconst SEND_ICON_SVG = '<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>';\nconst ICON_IMAGE = '<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>';\nconst ICON_PAPERCLIP = '<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>';\nconst ICON_MIC = '<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>';\nconst ICON_MIC_OFF = '<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>';\nconst FILE_ICON = '<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>';\n\nconst STATUS_MAP: Record<MessageStatus, string> = {\n sending: '...',\n sent: '✓',\n delivered: '✓✓',\n read: '✓✓',\n failed: '!',\n};\n\nexport class DOMRenderer {\n private container: HTMLElement;\n private config: ChatConfig;\n private emitter: EventEmitter;\n private mentionEngine: MentionEngine;\n private prefix: string;\n\n private root!: HTMLElement;\n private messageListEl!: HTMLElement;\n private inputArea: HTMLElement | null = null;\n private textareaEl: HTMLTextAreaElement | null = null;\n private sendBtn: HTMLButtonElement | null = null;\n private mentionPanel: HTMLElement | null = null;\n private loadMoreEl: HTMLElement | null = null;\n private toolbarEl: HTMLElement | null = null;\n private dropOverlay: HTMLElement | null = null;\n private voiceBtn: HTMLElement | null = null;\n private loadingMore = false;\n private isRecording = false;\n private recognition: any = null;\n private lastVoiceTranscript = '';\n\n constructor(\n container: HTMLElement,\n config: ChatConfig,\n emitter: EventEmitter,\n mentionEngine: MentionEngine,\n ) {\n this.container = container;\n this.config = config;\n this.emitter = emitter;\n this.mentionEngine = mentionEngine;\n this.prefix = normalizeClassPrefix(config.classPrefix ?? DEFAULT_CLASS_PREFIX);\n }\n\n init(): void {\n this.container.innerHTML = '';\n this.root = this.el('div', `${this.prefix}-container`);\n this.messageListEl = this.el('div', `${this.prefix}-message-list`);\n this.root.appendChild(this.messageListEl);\n\n if (this.config.showInput !== false) {\n this.renderInputArea();\n }\n\n this.container.appendChild(this.root);\n this.setupEventListeners();\n }\n\n updateMessageContent(id: string, content: string): void {\n const rowEl = this.messageListEl.querySelector(`[data-msg-id=\"${this.escapeAttr(id)}\"]`) as HTMLElement | null;\n const bubble = rowEl?.querySelector(`.${this.prefix}-bubble`) as HTMLElement | null;\n if (!bubble) return;\n bubble.innerHTML = this.renderTextContent(content);\n }\n\n renderMessages(messages: ChatMessage[]): void {\n this.messageListEl.innerHTML = '';\n\n if (this.config.enableLoadMore) {\n this.renderLoadMoreButton();\n }\n\n if (messages.length === 0) {\n this.renderEmpty();\n return;\n }\n\n let lastTimestamp = 0;\n const interval = this.config.timeGroupInterval ?? 300000;\n for (const message of messages) {\n if (this.config.showTimestamp !== false && message.timestamp - lastTimestamp > interval) {\n this.renderTimeDivider(message.timestamp);\n lastTimestamp = message.timestamp;\n }\n this.renderMessageRow(message);\n }\n }\n\n appendMessage(message: ChatMessage): void {\n this.removeEmpty();\n const messageEls = this.getMessageElements();\n const lastTime = messageEls.length > 0\n ? Number.parseInt(messageEls[messageEls.length - 1].dataset.timestamp ?? '0', 10)\n : 0;\n const interval = this.config.timeGroupInterval ?? 300000;\n\n if (this.config.showTimestamp !== false && message.timestamp - lastTime > interval) {\n this.renderTimeDivider(message.timestamp);\n }\n\n this.renderMessageRow(message);\n }\n\n prependMessages(messages: ChatMessage[]): void {\n if (!messages.length) return;\n this.removeEmpty();\n\n const scrollHeight = this.messageListEl.scrollHeight;\n const scrollTop = this.messageListEl.scrollTop;\n const fragment = document.createDocumentFragment();\n let lastTimestamp = 0;\n const interval = this.config.timeGroupInterval ?? 300000;\n\n for (const message of messages) {\n if (this.config.showTimestamp !== false && message.timestamp - lastTimestamp > interval) {\n fragment.appendChild(this.createTimeDivider(message.timestamp));\n lastTimestamp = message.timestamp;\n }\n fragment.appendChild(this.createMessageRow(message));\n }\n\n const firstMessage = this.messageListEl.querySelector(`.${this.prefix}-message-row, .${this.prefix}-time-divider`);\n if (firstMessage) {\n firstMessage.before(fragment);\n } else if (this.loadMoreEl) {\n this.loadMoreEl.after(fragment);\n } else {\n this.messageListEl.appendChild(fragment);\n }\n\n this.messageListEl.scrollTop = scrollTop + (this.messageListEl.scrollHeight - scrollHeight);\n }\n\n updateMessage(id: string, message: ChatMessage): void {\n const rowEl = this.messageListEl.querySelector(`[data-msg-id=\"${this.escapeAttr(id)}\"]`);\n if (!rowEl) return;\n rowEl.replaceWith(this.createMessageRow(message));\n }\n\n removeMessage(id: string): void {\n this.messageListEl.querySelector(`[data-msg-id=\"${this.escapeAttr(id)}\"]`)?.remove();\n if (this.getMessageElements().length === 0) {\n this.renderEmpty();\n }\n }\n\n scrollToBottom(smooth = true): void {\n if (typeof this.messageListEl.scrollTo === 'function') {\n this.messageListEl.scrollTo({\n top: this.messageListEl.scrollHeight,\n behavior: smooth ? 'smooth' : 'auto',\n });\n return;\n }\n this.messageListEl.scrollTop = this.messageListEl.scrollHeight;\n }\n\n isAtBottom(threshold = 4): boolean {\n const distance = this.messageListEl.scrollHeight - this.messageListEl.scrollTop - this.messageListEl.clientHeight;\n return distance <= threshold;\n }\n\n setLoadingMore(loading: boolean): void {\n this.loadingMore = loading;\n if (!this.loadMoreEl) return;\n this.loadMoreEl.textContent = loading ? '加载中...' : (this.config.loadMoreText ?? '加载更多');\n this.loadMoreEl.classList.toggle(`${this.prefix}-load-more--loading`, loading);\n }\n\n focusInput(): void {\n this.textareaEl?.focus();\n }\n\n setInputContent(content: string): void {\n if (!this.textareaEl) return;\n this.textareaEl.value = this.limitInput(content);\n this.autoResize();\n this.updateSendButtonState();\n this.config.onInputChange?.(this.textareaEl.value);\n }\n\n getInputContent(): string {\n return this.textareaEl?.value ?? '';\n }\n\n clearInput(): void {\n this.setInputContent('');\n }\n\n renderMentionPanel(members: MentionItem[], activeIndex: number): void {\n if (!this.mentionPanel) return;\n\n if (members.length === 0) {\n this.mentionPanel.style.display = 'none';\n return;\n }\n\n this.mentionPanel.style.display = 'block';\n this.mentionPanel.innerHTML = '';\n\n members.forEach((member, index) => {\n const item = this.el(\n 'div',\n cx(`${this.prefix}-mention-item`, index === activeIndex && `${this.prefix}-mention-item--active`),\n );\n item.setAttribute('role', 'option');\n item.setAttribute('aria-selected', String(index === activeIndex));\n\n const avatar = this.el('div', `${this.prefix}-mention-item-avatar`);\n if (member.avatar) {\n const img = document.createElement('img');\n img.src = member.avatar;\n img.alt = '';\n avatar.appendChild(img);\n } else {\n avatar.textContent = member.name[0]?.toUpperCase() ?? '';\n }\n item.appendChild(avatar);\n\n const name = this.el('span', `${this.prefix}-mention-item-name`);\n name.textContent = member.name;\n item.appendChild(name);\n\n item.addEventListener('click', () => {\n this.mentionEngine.select(index);\n });\n\n this.mentionPanel?.appendChild(item);\n });\n }\n\n hideMentionPanel(): void {\n if (this.mentionPanel) {\n this.mentionPanel.style.display = 'none';\n }\n }\n\n destroy(): void {\n this.stopVoice();\n this.container.innerHTML = '';\n }\n\n private renderInputArea(): void {\n this.inputArea = this.el('div', `${this.prefix}-input-area`);\n const wrapper = this.el('div', `${this.prefix}-input-wrapper`);\n\n this.mentionPanel = this.el('div', `${this.prefix}-mention-panel`);\n this.mentionPanel.style.display = 'none';\n this.mentionPanel.setAttribute('role', 'listbox');\n wrapper.appendChild(this.mentionPanel);\n\n if (this.config.enableToolbar !== false) {\n this.renderToolbar(wrapper);\n }\n\n this.textareaEl = document.createElement('textarea');\n this.textareaEl.className = `${this.prefix}-textarea`;\n this.textareaEl.placeholder = this.config.inputPlaceholder ?? '输入消息...';\n this.textareaEl.rows = 1;\n if (this.config.maxInputLength && this.config.maxInputLength > 0) {\n this.textareaEl.maxLength = this.config.maxInputLength;\n }\n wrapper.appendChild(this.textareaEl);\n\n this.dropOverlay = this.el('div', `${this.prefix}-drop-overlay`);\n this.dropOverlay.innerHTML = '<span>拖放文件到这里</span>';\n this.dropOverlay.style.display = 'none';\n wrapper.appendChild(this.dropOverlay);\n\n this.inputArea.appendChild(wrapper);\n\n this.sendBtn = document.createElement('button');\n this.sendBtn.className = `${this.prefix}-send-btn`;\n this.sendBtn.innerHTML = SEND_ICON_SVG;\n this.sendBtn.title = '发送';\n this.sendBtn.type = 'button';\n this.sendBtn.disabled = true;\n this.inputArea.appendChild(this.sendBtn);\n\n this.root.appendChild(this.inputArea);\n }\n\n private renderToolbar(wrapper: HTMLElement): void {\n const toolbar = this.config.toolbarConfig ?? {};\n this.toolbarEl = this.el('div', `${this.prefix}-toolbar`);\n\n if (toolbar.image !== false) {\n const imageBtn = this.createToolbarBtn(ICON_IMAGE, '插入图片');\n imageBtn.addEventListener('click', () => this.openFilePicker('image/*'));\n this.toolbarEl.appendChild(imageBtn);\n }\n\n if (toolbar.file !== false) {\n const fileBtn = this.createToolbarBtn(ICON_PAPERCLIP, '插入文件');\n fileBtn.addEventListener('click', () => this.openFilePicker('*/*'));\n this.toolbarEl.appendChild(fileBtn);\n }\n\n if (toolbar.voice !== false) {\n this.voiceBtn = this.createToolbarBtn(ICON_MIC, '语音输入');\n this.voiceBtn.addEventListener('click', () => this.toggleVoice());\n this.toolbarEl.appendChild(this.voiceBtn);\n }\n\n wrapper.insertBefore(this.toolbarEl, wrapper.firstChild);\n }\n\n private createToolbarBtn(iconSvg: string, title: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.className = `${this.prefix}-toolbar-btn`;\n btn.innerHTML = iconSvg;\n btn.title = title;\n btn.type = 'button';\n return btn;\n }\n\n private openFilePicker(accept: string): void {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = accept;\n input.multiple = true;\n input.style.display = 'none';\n input.addEventListener('change', () => {\n const files = Array.from(input.files ?? []);\n input.remove();\n if (!files.length) return;\n const isImage = accept.startsWith('image');\n this.emitter.emit(isImage ? 'toolbar-image' : 'toolbar-file', files);\n if (isImage) {\n this.config.onImageUpload?.(files);\n } else {\n this.config.onFileUpload?.(files);\n }\n });\n document.body.appendChild(input);\n input.click();\n }\n\n private toggleVoice(): void {\n if (this.isRecording) {\n this.stopVoice();\n } else {\n this.startVoice();\n }\n }\n\n private startVoice(): void {\n if (typeof window === 'undefined') return;\n const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;\n if (!SpeechRecognition) {\n this.emitter.emit('toolbar-voice-unsupported');\n this.config.onVoiceUnsupported?.();\n return;\n }\n\n try {\n this.lastVoiceTranscript = '';\n this.recognition = new SpeechRecognition();\n this.recognition.continuous = false;\n this.recognition.interimResults = true;\n this.recognition.lang = this.config.voiceLang ?? 'zh-CN';\n\n this.recognition.onresult = (event: any) => {\n let transcript = '';\n for (let i = 0; i < event.results.length; i++) {\n transcript += event.results[i][0].transcript;\n }\n this.lastVoiceTranscript = transcript;\n const lastResult = event.results[event.results.length - 1];\n if (lastResult?.isFinal && this.textareaEl) {\n this.insertTextAtCursor(transcript);\n }\n };\n\n this.recognition.onend = () => {\n this.finishVoice();\n this.emitter.emit('toolbar-voice-end', this.lastVoiceTranscript);\n this.config.onVoiceEnd?.(this.lastVoiceTranscript);\n };\n\n this.recognition.onerror = (error: unknown) => {\n this.finishVoice();\n this.emitter.emit('toolbar-voice-error', error);\n this.config.onVoiceError?.(error);\n };\n\n this.isRecording = true;\n this.voiceBtn?.classList.add(`${this.prefix}-toolbar-btn--active`);\n if (this.voiceBtn) this.voiceBtn.innerHTML = ICON_MIC_OFF;\n this.recognition.start();\n this.emitter.emit('toolbar-voice-start');\n this.config.onVoiceStart?.();\n } catch (error) {\n this.finishVoice();\n this.emitter.emit('toolbar-voice-error', error);\n this.config.onVoiceError?.(error);\n }\n }\n\n private stopVoice(): void {\n if (!this.recognition) return;\n const recognition = this.recognition;\n this.recognition = null;\n try {\n recognition.stop();\n } catch {\n this.finishVoice();\n }\n }\n\n private finishVoice(): void {\n this.isRecording = false;\n this.recognition = null;\n this.voiceBtn?.classList.remove(`${this.prefix}-toolbar-btn--active`);\n if (this.voiceBtn) this.voiceBtn.innerHTML = ICON_MIC;\n }\n\n private setupEventListeners(): void {\n if (this.textareaEl) {\n this.textareaEl.addEventListener('input', () => {\n const limited = this.limitInput(this.textareaEl?.value ?? '');\n if (this.textareaEl && limited !== this.textareaEl.value) {\n this.textareaEl.value = limited;\n }\n this.autoResize();\n this.updateSendButtonState();\n this.config.onInputChange?.(this.textareaEl?.value ?? '');\n if (this.config.enableMention && this.textareaEl) {\n this.mentionEngine.handleInput(this.textareaEl.value, this.textareaEl.selectionStart);\n }\n });\n\n this.textareaEl.addEventListener('keydown', (event) => {\n const mentionState = this.mentionEngine.getState();\n\n if (mentionState.active) {\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n this.mentionEngine.moveUp();\n } else if (event.key === 'ArrowDown') {\n event.preventDefault();\n this.mentionEngine.moveDown();\n } else if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n const member = this.mentionEngine.selectCurrent();\n if (member) this.insertMention(member);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n this.mentionEngine.deactivate();\n }\n return;\n }\n\n if (this.config.enterToSend !== false && event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.handleSend();\n }\n });\n\n this.textareaEl.addEventListener('paste', (event) => {\n const items = event.clipboardData?.items;\n if (!items) return;\n const files: File[] = [];\n for (let i = 0; i < items.length; i++) {\n if (items[i].kind === 'file') {\n const file = items[i].getAsFile();\n if (file) files.push(file);\n }\n }\n if (files.length > 0) {\n event.preventDefault();\n this.emitter.emit('toolbar-paste', files);\n this.config.onPaste?.(files);\n }\n });\n }\n\n if (this.inputArea) {\n const wrapper = this.inputArea.querySelector(`.${this.prefix}-input-wrapper`) as HTMLElement | null;\n if (wrapper) this.setupDropEvents(wrapper);\n }\n\n this.sendBtn?.addEventListener('click', () => {\n this.handleSend();\n });\n\n this.emitter.on('mention-filter', (state: { filtered: MentionItem[]; activeIndex: number }) => {\n this.renderMentionPanel(state.filtered, state.activeIndex);\n });\n this.emitter.on('mention-active-change', (index: number) => {\n const items = this.mentionPanel?.querySelectorAll(`.${this.prefix}-mention-item`);\n items?.forEach((el, i) => {\n el.classList.toggle(`${this.prefix}-mention-item--active`, i === index);\n el.setAttribute('aria-selected', String(i === index));\n });\n });\n this.emitter.on('mention-deactivate', () => {\n this.hideMentionPanel();\n });\n }\n\n private setupDropEvents(wrapper: HTMLElement): void {\n let dragCounter = 0;\n wrapper.addEventListener('dragenter', (event) => {\n event.preventDefault();\n dragCounter++;\n if (this.dropOverlay) this.dropOverlay.style.display = 'flex';\n });\n wrapper.addEventListener('dragleave', (event) => {\n event.preventDefault();\n dragCounter--;\n if (dragCounter <= 0) {\n dragCounter = 0;\n if (this.dropOverlay) this.dropOverlay.style.display = 'none';\n }\n });\n wrapper.addEventListener('dragover', (event) => {\n event.preventDefault();\n });\n wrapper.addEventListener('drop', (event) => {\n event.preventDefault();\n dragCounter = 0;\n if (this.dropOverlay) this.dropOverlay.style.display = 'none';\n const files = Array.from(event.dataTransfer?.files ?? []);\n if (files.length > 0) {\n this.emitter.emit('toolbar-drop', files);\n this.config.onDrop?.(files);\n }\n });\n }\n\n private handleSend(): void {\n const rawContent = this.textareaEl?.value ?? '';\n const content = rawContent.trim();\n if (!content) return;\n\n const mentions = this.mentionEngine.parseMentions(content);\n this.emitter.emit('send', content, mentions);\n this.config.onSend?.(content, mentions);\n\n if (this.config.clearInputOnSend !== false) {\n this.clearInput();\n }\n this.mentionEngine.resetSelected();\n }\n\n private insertMention(member: MentionItem): void {\n if (!this.textareaEl) return;\n const state = this.mentionEngine.getState();\n const text = this.textareaEl.value;\n const pos = this.textareaEl.selectionStart;\n const insertText = this.mentionEngine.getInsertText(member);\n\n const before = text.slice(0, state.triggerPosition);\n const after = text.slice(pos);\n this.textareaEl.value = this.limitInput(before + insertText + after);\n const newPos = Math.min(before.length + insertText.length, this.textareaEl.value.length);\n this.textareaEl.setSelectionRange(newPos, newPos);\n this.textareaEl.focus();\n this.autoResize();\n this.updateSendButtonState();\n this.config.onInputChange?.(this.textareaEl.value);\n }\n\n private insertTextAtCursor(text: string): void {\n if (!this.textareaEl) return;\n const current = this.textareaEl.value;\n const start = this.textareaEl.selectionStart;\n const end = this.textareaEl.selectionEnd;\n this.textareaEl.value = this.limitInput(current.slice(0, start) + text + current.slice(end));\n const nextCursor = Math.min(start + text.length, this.textareaEl.value.length);\n this.textareaEl.setSelectionRange(nextCursor, nextCursor);\n this.autoResize();\n this.updateSendButtonState();\n this.config.onInputChange?.(this.textareaEl.value);\n }\n\n private autoResize(): void {\n if (!this.textareaEl) return;\n this.textareaEl.style.height = 'auto';\n const maxHeight = this.getCssSizeValue('--ldesign-chat-textarea-max-height', 120);\n this.textareaEl.style.height = `${Math.min(this.textareaEl.scrollHeight, maxHeight)}px`;\n }\n\n private updateSendButtonState(): void {\n if (!this.sendBtn) return;\n this.sendBtn.disabled = !this.getInputContent().trim();\n }\n\n private renderLoadMoreButton(): void {\n this.loadMoreEl = this.el('div', `${this.prefix}-load-more`);\n this.loadMoreEl.textContent = this.config.loadMoreText ?? '加载更多';\n this.loadMoreEl.addEventListener('click', () => {\n if (this.loadingMore) return;\n this.setLoadingMore(true);\n this.emitter.emit('load-more');\n Promise.resolve(this.config.onLoadMore?.()).finally(() => {\n this.setLoadingMore(false);\n });\n });\n this.messageListEl.appendChild(this.loadMoreEl);\n }\n\n private renderTimeDivider(timestamp: number): void {\n this.messageListEl.appendChild(this.createTimeDivider(timestamp));\n }\n\n private createTimeDivider(timestamp: number): HTMLElement {\n const divider = this.el('div', `${this.prefix}-time-divider`);\n const span = document.createElement('span');\n span.textContent = this.formatTime(timestamp);\n divider.appendChild(span);\n return divider;\n }\n\n private renderMessageRow(message: ChatMessage): void {\n this.messageListEl.appendChild(this.createMessageRow(message));\n }\n\n private createMessageRow(message: ChatMessage): HTMLElement {\n const p = this.prefix;\n\n if (message.type === 'system') {\n const row = this.el('div', cx(`${p}-message-row`, `${p}-message-row--system`));\n row.dataset.msgId = message.id;\n row.dataset.timestamp = String(message.timestamp);\n const system = this.el('div', `${p}-system-message`);\n system.textContent = message.content ?? '';\n row.appendChild(system);\n return row;\n }\n\n const isOutgoing = message.direction === 'outgoing';\n const row = this.el('div', cx(`${p}-message-row`, isOutgoing && `${p}-message-row--outgoing`));\n row.dataset.msgId = message.id;\n row.dataset.timestamp = String(message.timestamp);\n\n if (this.config.showAvatar !== false) {\n row.appendChild(this.createAvatar(message.sender.nickname, message.sender.avatar));\n }\n\n const body = this.el('div', `${p}-message-body`);\n if (this.config.showNickname !== false && !isOutgoing) {\n const nickname = this.el('div', `${p}-nickname`);\n nickname.textContent = message.sender.nickname;\n body.appendChild(nickname);\n }\n\n body.appendChild(this.createBubble(message, isOutgoing));\n body.appendChild(this.createMessageFooter(message, isOutgoing));\n row.appendChild(body);\n\n row.addEventListener('click', () => {\n this.emitter.emit('message-click', message);\n this.config.onMessageClick?.(message);\n });\n\n return row;\n }\n\n private createAvatar(name: string, avatarUrl?: string): HTMLElement {\n const avatar = this.el('div', `${this.prefix}-avatar`);\n if (avatarUrl) {\n const img = document.createElement('img');\n img.src = avatarUrl;\n img.alt = name;\n avatar.appendChild(img);\n } else {\n avatar.textContent = name[0]?.toUpperCase() ?? '';\n }\n return avatar;\n }\n\n private createMessageFooter(message: ChatMessage, isOutgoing: boolean): HTMLElement {\n const footer = this.el('div', `${this.prefix}-message-footer`);\n if (this.config.showTimestamp !== false) {\n const time = this.el('span', `${this.prefix}-timestamp`);\n time.textContent = this.formatShortTime(message.timestamp);\n footer.appendChild(time);\n }\n if (this.config.showStatus !== false && isOutgoing && message.status) {\n const status = this.el('span', cx(`${this.prefix}-status`, `${this.prefix}-status--${message.status}`));\n status.textContent = STATUS_MAP[message.status] ?? '';\n if (message.status === 'failed') {\n status.addEventListener('click', (event) => {\n event.stopPropagation();\n this.emitter.emit('message-retry', message);\n });\n }\n footer.appendChild(status);\n }\n return footer;\n }\n\n private createBubble(message: ChatMessage, isOutgoing: boolean): HTMLElement {\n const p = this.prefix;\n const dirClass = isOutgoing ? `${p}-bubble--outgoing` : `${p}-bubble--incoming`;\n\n if (message.revoked) {\n const bubble = this.el('div', cx(`${p}-bubble`, dirClass, `${p}-bubble--revoked`));\n bubble.textContent = '消息已撤回';\n return bubble;\n }\n\n switch (message.type) {\n case 'image': {\n const bubble = this.el('div', cx(`${p}-bubble`, dirClass, `${p}-bubble--image`));\n if (message.image) {\n const img = document.createElement('img');\n img.src = message.image.thumbUrl ?? message.image.url;\n img.alt = message.content ?? '';\n if (message.image.width) img.width = Math.min(message.image.width, 240);\n bubble.appendChild(img);\n }\n return bubble;\n }\n\n case 'file': {\n const bubble = this.el('div', cx(`${p}-bubble`, dirClass, `${p}-bubble--file`));\n const icon = this.el('div', `${p}-file-icon`);\n icon.innerHTML = FILE_ICON;\n bubble.appendChild(icon);\n\n const info = this.el('div', `${p}-file-info`);\n const name = this.el('div', `${p}-file-name`);\n name.textContent = message.file?.name ?? 'file';\n info.appendChild(name);\n\n if (message.file?.size) {\n const size = this.el('div', `${p}-file-size`);\n size.textContent = this.formatFileSize(message.file.size);\n info.appendChild(size);\n }\n bubble.appendChild(info);\n return bubble;\n }\n\n case 'custom': {\n const bubble = this.el('div', cx(`${p}-bubble`, dirClass));\n if (message.customHtml) {\n bubble.innerHTML = message.customHtml;\n } else {\n bubble.textContent = message.content ?? '';\n }\n return bubble;\n }\n\n default: {\n const bubble = this.el('div', cx(`${p}-bubble`, dirClass, message.streaming && `${p}-bubble--streaming`));\n bubble.innerHTML = this.renderTextContent(message.content ?? '', message.mentions);\n return bubble;\n }\n }\n }\n\n private renderTextContent(content: string, mentions?: MentionItem[]): string {\n let html = this.escapeHtml(content);\n\n if (mentions?.length) {\n for (const mention of mentions) {\n const tag = `<span class=\"${this.prefix}-mention-tag\" data-mention-id=\"${this.escapeAttr(mention.id)}\">@${this.escapeHtml(mention.name)}</span>`;\n html = html.replace(new RegExp(`@${this.escapeRegex(mention.name)}`, 'g'), tag);\n }\n }\n\n return html.replace(\n /(https?:\\/\\/[^\\s<]+)/g,\n `<a class=\"${this.prefix}-link\" href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>`,\n );\n }\n\n private renderEmpty(): void {\n if (this.messageListEl.querySelector(`.${this.prefix}-empty`)) return;\n const empty = this.el('div', `${this.prefix}-empty`);\n empty.textContent = '暂无消息';\n this.messageListEl.appendChild(empty);\n }\n\n private removeEmpty(): void {\n this.messageListEl.querySelector(`.${this.prefix}-empty`)?.remove();\n }\n\n private el(tag: string, className: string): HTMLElement {\n const el = document.createElement(tag);\n el.className = className;\n return el;\n }\n\n private getMessageElements(): HTMLElement[] {\n return Array.from(this.messageListEl.querySelectorAll<HTMLElement>(`.${this.prefix}-message-row`));\n }\n\n private formatTime(timestamp: number): string {\n if (this.config.formatTime) return this.config.formatTime(timestamp);\n const date = new Date(timestamp);\n const now = new Date();\n const isToday = date.toDateString() === now.toDateString();\n if (isToday) {\n return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });\n }\n return date.toLocaleDateString('zh-CN', {\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n }\n\n private formatShortTime(timestamp: number): string {\n return new Date(timestamp).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });\n }\n\n private formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n\n private limitInput(content: string): string {\n const max = this.config.maxInputLength;\n if (!max || max <= 0) return content;\n return content.slice(0, max);\n }\n\n private getCssSizeValue(name: string, fallback: number): number {\n if (typeof window === 'undefined' || !this.root) return fallback;\n const value = window.getComputedStyle(this.root).getPropertyValue(name).trim();\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) ? parsed : fallback;\n }\n\n private escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n private escapeAttr(str: string): string {\n return str\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n }\n\n private escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n}\n","/**\n * @file style-manager.ts\n * @description style-manager 模块\n */\n\nimport type { ThemeTokens } from '../theme/tokens';\nimport {\n COMPONENT_CSS_VAR_PREFIX,\n DEFAULT_CLASS_PREFIX,\n cx,\n getStyleElementId,\n normalizeClassPrefix,\n} from '../constants/dom';\n\nconst styleRefs = new Map<string, number>();\n\n/**\n * injectStyles 函数\n * @param tokens - 参数\n * @param prefix - 参数\n * @returns 返回值\n */\n/**\n * injectStyles - inject Styles function\n * @param tokens - 参数说明\n * @param prefix - 参数说明\n * @returns 返回值说明\n */\nexport function injectStyles(tokens: ThemeTokens, prefix: string = DEFAULT_CLASS_PREFIX): void {\n const normalizedPrefix = normalizeClassPrefix(prefix);\n const styleId = getStyleElementId(normalizedPrefix);\n styleRefs.set(styleId, (styleRefs.get(styleId) ?? 0) + 1);\n upsertStyle(styleId, generateCSS(tokens, normalizedPrefix));\n}\n\n/**\n * updateStyles 函数\n * @param tokens - 参数\n * @param prefix - 参数\n * @returns 返回值\n */\n/**\n * updateStyles - update Styles function\n * @param tokens - 参数说明\n * @param prefix - 参数说明\n * @returns 返回值说明\n */\nexport function updateStyles(tokens: ThemeTokens, prefix: string = DEFAULT_CLASS_PREFIX): void {\n const normalizedPrefix = normalizeClassPrefix(prefix);\n const styleId = getStyleElementId(normalizedPrefix);\n upsertStyle(styleId, generateCSS(tokens, normalizedPrefix));\n}\n\n/**\n * removeStyles 函数\n * @param prefix - 参数\n * @returns 返回值\n */\n/**\n * removeStyles - remove Styles function\n * @param prefix - 参数说明\n * @returns 返回值说明\n */\nexport function removeStyles(prefix: string = DEFAULT_CLASS_PREFIX): void {\n const styleId = getStyleElementId(prefix);\n const refs = styleRefs.get(styleId) ?? 0;\n if (refs > 1) {\n styleRefs.set(styleId, refs - 1);\n return;\n }\n\n styleRefs.delete(styleId);\n document.getElementById(styleId)?.remove();\n}\n\n/**\n * cls 函数\n * @param prefix - 参数\n * @param ...parts - 参数\n * @returns 返回值\n */\n/**\n * cls - cls function\n * @param prefix - 参数说明\n * @param ...parts - 参数说明\n * @returns 返回值说明\n */\nexport function cls(prefix: string, ...parts: string[]): string {\n const normalizedPrefix = normalizeClassPrefix(prefix);\n return parts.map((part) => `${normalizedPrefix}-${part}`).join(' ');\n}\n\nexport const clsx = cx;\n\nfunction upsertStyle(styleId: string, cssText: string): void {\n let style = document.getElementById(styleId) as HTMLStyleElement | null;\n if (!style) {\n style = document.createElement('style');\n style.id = styleId;\n style.dataset.ldesignChat = 'true';\n document.head.appendChild(style);\n }\n style.textContent = cssText;\n}\n\nfunction tokenVars(t: ThemeTokens): string {\n const vars: Record<string, string> = {\n bgPrimary: t.bgPrimary,\n bgSecondary: t.bgSecondary,\n bgBubbleOutgoing: t.bgBubbleOutgoing,\n bgBubbleIncoming: t.bgBubbleIncoming,\n bgInput: t.bgInput,\n bgMention: t.bgMention,\n bgMentionHover: t.bgMentionHover,\n bgMentionActive: t.bgMentionActive,\n bgLoadMore: t.bgLoadMore,\n bgSystemMessage: t.bgSystemMessage,\n bgDropOverlay: t.bgDropOverlay,\n bgDangerSoft: t.bgDangerSoft,\n textPrimary: t.textPrimary,\n textSecondary: t.textSecondary,\n textBubbleOutgoing: t.textBubbleOutgoing,\n textBubbleIncoming: t.textBubbleIncoming,\n textMention: t.textMention,\n textMentionTag: t.textMentionTag,\n textTimestamp: t.textTimestamp,\n textSystem: t.textSystem,\n textPlaceholder: t.textPlaceholder,\n borderPrimary: t.borderPrimary,\n borderInput: t.borderInput,\n borderInputFocus: t.borderInputFocus,\n borderMention: t.borderMention,\n colorSending: t.colorSending,\n colorSent: t.colorSent,\n colorDelivered: t.colorDelivered,\n colorRead: t.colorRead,\n colorFailed: t.colorFailed,\n colorLink: t.colorLink,\n shadowPanel: t.shadowPanel,\n shadowMention: t.shadowMention,\n avatarBg: t.avatarBg,\n avatarText: t.avatarText,\n btnPrimaryBg: t.btnPrimaryBg,\n btnPrimaryText: t.btnPrimaryText,\n btnPrimaryHover: t.btnPrimaryHover,\n scrollbarThumb: t.scrollbarThumb,\n scrollbarTrack: t.scrollbarTrack,\n bgToolbar: t.bgToolbar,\n borderToolbar: t.borderToolbar,\n toolbarIconColor: t.toolbarIconColor,\n toolbarIconHover: t.toolbarIconHover,\n toolbarVoiceActive: t.toolbarVoiceActive,\n };\n\n return Object.entries(vars)\n .map(([key, value]) => ` ${COMPONENT_CSS_VAR_PREFIX}-${toKebab(key)}: ${value};`)\n .join('\\n');\n}\n\nfunction sizeVars(): string {\n return `\n ${COMPONENT_CSS_VAR_PREFIX}-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;\n ${COMPONENT_CSS_VAR_PREFIX}-font-size: var(--size-font-base);\n ${COMPONENT_CSS_VAR_PREFIX}-font-size-sm: var(--size-font-sm);\n ${COMPONENT_CSS_VAR_PREFIX}-font-size-xs: var(--size-font-xs);\n ${COMPONENT_CSS_VAR_PREFIX}-font-size-lg: var(--size-font-lg);\n ${COMPONENT_CSS_VAR_PREFIX}-font-weight-regular: var(--size-font-weight-regular);\n ${COMPONENT_CSS_VAR_PREFIX}-font-weight-medium: var(--size-font-weight-medium);\n ${COMPONENT_CSS_VAR_PREFIX}-font-weight-semibold: var(--size-font-weight-semibold);\n ${COMPONENT_CSS_VAR_PREFIX}-line-height: var(--size-line-normal);\n ${COMPONENT_CSS_VAR_PREFIX}-line-height-bubble: var(--size-line-relaxed);\n ${COMPONENT_CSS_VAR_PREFIX}-space-1: var(--size-1);\n ${COMPONENT_CSS_VAR_PREFIX}-space-2: var(--size-2);\n ${COMPONENT_CSS_VAR_PREFIX}-space-3: var(--size-3);\n ${COMPONENT_CSS_VAR_PREFIX}-space-4: var(--size-4);\n ${COMPONENT_CSS_VAR_PREFIX}-space-5: var(--size-5);\n ${COMPONENT_CSS_VAR_PREFIX}-space-6: var(--size-6);\n ${COMPONENT_CSS_VAR_PREFIX}-space-8: var(--size-8);\n ${COMPONENT_CSS_VAR_PREFIX}-avatar-size: var(--size-11);\n ${COMPONENT_CSS_VAR_PREFIX}-mention-avatar-size: var(--size-9);\n ${COMPONENT_CSS_VAR_PREFIX}-toolbar-button-size: var(--size-9);\n ${COMPONENT_CSS_VAR_PREFIX}-input-button-size: var(--size-11);\n ${COMPONENT_CSS_VAR_PREFIX}-file-icon-size: var(--size-12);\n ${COMPONENT_CSS_VAR_PREFIX}-image-max-size: calc(var(--size-13) * 5);\n ${COMPONENT_CSS_VAR_PREFIX}-panel-max-height: calc(var(--size-24) + var(--size-4));\n ${COMPONENT_CSS_VAR_PREFIX}-textarea-min-height: var(--size-11);\n ${COMPONENT_CSS_VAR_PREFIX}-textarea-max-height: calc(var(--size-12) * 3);\n ${COMPONENT_CSS_VAR_PREFIX}-message-max-width: 65%;\n ${COMPONENT_CSS_VAR_PREFIX}-system-message-max-width: 80%;\n ${COMPONENT_CSS_VAR_PREFIX}-file-bubble-min-width: calc(var(--size-24) + var(--size-4));\n ${COMPONENT_CSS_VAR_PREFIX}-border-width: var(--size-border-width-thin);\n ${COMPONENT_CSS_VAR_PREFIX}-border-width-drop: var(--size-border-width-medium);\n ${COMPONENT_CSS_VAR_PREFIX}-radius-xs: var(--size-radius-sm);\n ${COMPONENT_CSS_VAR_PREFIX}-radius-sm: var(--size-radius-md);\n ${COMPONENT_CSS_VAR_PREFIX}-radius-md: var(--size-radius-lg);\n ${COMPONENT_CSS_VAR_PREFIX}-radius-lg: var(--size-radius-xl);\n ${COMPONENT_CSS_VAR_PREFIX}-radius-pill: var(--size-radius-full);\n ${COMPONENT_CSS_VAR_PREFIX}-radius-circle: var(--size-radius-circle);\n ${COMPONENT_CSS_VAR_PREFIX}-transition-fast: var(--size-duration-fast) var(--size-ease-out);\n ${COMPONENT_CSS_VAR_PREFIX}-transition-normal: var(--size-duration-normal) var(--size-ease-out);\n ${COMPONENT_CSS_VAR_PREFIX}-z-overlay: var(--size-z-dropdown);\n ${COMPONENT_CSS_VAR_PREFIX}-z-mention: var(--size-z-popover);\n`;\n}\n\nfunction generateCSS(tokens: ThemeTokens, p: string): string {\n return `\n/* @composy/chat-core styles */\n.${p}-container,\n.${p}-container * {\n box-sizing: border-box;\n}\n\n.${p}-container {\n${tokenVars(tokens)}\n${sizeVars()}\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: hidden;\n position: relative;\n background: ${v('bg-primary')};\n color: ${v('text-primary')};\n font-family: ${v('font-family')};\n font-size: ${v('font-size')};\n line-height: ${v('line-height')};\n border: ${v('border-width')} solid ${v('border-primary')};\n border-radius: ${v('radius-md')};\n box-shadow: ${v('shadow-panel')};\n}\n\n.${p}-message-list {\n flex: 1;\n min-width: 0;\n overflow-y: auto;\n overflow-x: hidden;\n padding: ${v('space-6')};\n scroll-behavior: smooth;\n}\n\n.${p}-message-list::-webkit-scrollbar {\n width: var(--size-3);\n}\n\n.${p}-message-list::-webkit-scrollbar-thumb {\n background: ${v('scrollbar-thumb')};\n border-radius: ${v('radius-pill')};\n}\n\n.${p}-message-list::-webkit-scrollbar-track {\n background: ${v('scrollbar-track')};\n}\n\n.${p}-load-more {\n margin-bottom: ${v('space-5')};\n padding: ${v('space-5')};\n text-align: center;\n color: ${v('color-link')};\n font-size: ${v('font-size-sm')};\n background: ${v('bg-load-more')};\n border-radius: ${v('radius-sm')};\n cursor: pointer;\n user-select: none;\n transition: opacity ${v('transition-fast')}, background ${v('transition-fast')};\n}\n\n.${p}-load-more:hover {\n background: ${v('bg-mention-hover')};\n}\n\n.${p}-load-more--loading {\n cursor: default;\n opacity: .6;\n}\n\n.${p}-time-divider {\n padding: ${v('space-4')} 0;\n color: ${v('text-timestamp')};\n font-size: ${v('font-size-sm')};\n text-align: center;\n user-select: none;\n}\n\n.${p}-time-divider span {\n padding: ${v('space-1')} ${v('space-5')};\n background: ${v('bg-secondary')};\n border-radius: ${v('radius-pill')};\n}\n\n.${p}-message-row {\n display: flex;\n align-items: flex-start;\n gap: ${v('space-4')};\n margin-bottom: ${v('space-5')};\n}\n\n.${p}-message-row--outgoing {\n flex-direction: row-reverse;\n}\n\n.${p}-message-row--system {\n justify-content: center;\n}\n\n.${p}-avatar {\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${v('avatar-size')};\n height: ${v('avatar-size')};\n overflow: hidden;\n flex-shrink: 0;\n color: ${v('avatar-text')};\n background: ${v('avatar-bg')};\n border-radius: ${v('radius-circle')};\n font-size: ${v('font-size')};\n font-weight: ${v('font-weight-semibold')};\n}\n\n.${p}-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.${p}-message-body {\n display: flex;\n flex-direction: column;\n max-width: ${v('message-max-width')};\n min-width: 0;\n}\n\n.${p}-message-row--outgoing .${p}-message-body {\n align-items: flex-end;\n}\n\n.${p}-nickname {\n margin-bottom: ${v('space-2')};\n padding: 0 ${v('space-2')};\n color: ${v('text-secondary')};\n font-size: ${v('font-size-sm')};\n}\n\n.${p}-bubble {\n position: relative;\n max-width: 100%;\n padding: ${v('space-5')} ${v('space-6')};\n border-radius: ${v('radius-lg')};\n word-break: break-word;\n overflow-wrap: unknownwhere;\n white-space: pre-wrap;\n line-height: ${v('line-height-bubble')};\n}\n\n.${p}-bubble--incoming {\n color: ${v('text-bubble-incoming')};\n background: ${v('bg-bubble-incoming')};\n border-top-left-radius: ${v('radius-xs')};\n}\n\n.${p}-bubble--outgoing {\n color: ${v('text-bubble-outgoing')};\n background: ${v('bg-bubble-outgoing')};\n border-top-right-radius: ${v('radius-xs')};\n}\n\n.${p}-bubble--image {\n padding: ${v('space-2')};\n background: unset;\n}\n\n.${p}-bubble--image img {\n display: block;\n max-width: ${v('image-max-size')};\n max-height: ${v('image-max-size')};\n border-radius: ${v('radius-md')};\n cursor: pointer;\n}\n\n.${p}-bubble--file {\n display: flex;\n align-items: center;\n gap: ${v('space-5')};\n min-width: ${v('file-bubble-min-width')};\n}\n\n.${p}-file-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${v('file-icon-size')};\n height: ${v('file-icon-size')};\n flex-shrink: 0;\n background: ${v('bg-secondary')};\n border-radius: ${v('radius-sm')};\n font-size: ${v('font-size-lg')};\n}\n\n.${p}-file-info {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n}\n\n.${p}-file-name {\n overflow: hidden;\n font-size: ${v('font-size')};\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.${p}-file-size {\n margin-top: ${v('space-1')};\n color: ${v('text-secondary')};\n font-size: ${v('font-size-sm')};\n}\n\n.${p}-system-message {\n max-width: ${v('system-message-max-width')};\n padding: ${v('space-2')} ${v('space-6')};\n color: ${v('text-system')};\n background: ${v('bg-system-message')};\n border-radius: ${v('radius-pill')};\n font-size: ${v('font-size-sm')};\n text-align: center;\n}\n\n.${p}-message-footer {\n display: flex;\n align-items: center;\n gap: ${v('space-3')};\n margin-top: ${v('space-1')};\n padding: 0 ${v('space-2')};\n}\n\n.${p}-message-row--outgoing .${p}-message-footer {\n flex-direction: row-reverse;\n}\n\n.${p}-timestamp,\n.${p}-status {\n font-size: ${v('font-size-xs')};\n}\n\n.${p}-timestamp {\n color: ${v('text-timestamp')};\n}\n\n.${p}-status--sending { color: ${v('color-sending')}; }\n.${p}-status--sent { color: ${v('color-sent')}; }\n.${p}-status--delivered { color: ${v('color-delivered')}; }\n.${p}-status--read { color: ${v('color-read')}; }\n.${p}-status--failed {\n color: ${v('color-failed')};\n cursor: pointer;\n}\n\n.${p}-mention-tag,\n.${p}-link {\n color: ${v('text-mention-tag')};\n font-weight: ${v('font-weight-medium')};\n}\n\n.${p}-mention-tag {\n cursor: pointer;\n}\n\n.${p}-mention-tag:hover,\n.${p}-link:hover {\n text-decoration: underline;\n}\n\n.${p}-input-area {\n display: flex;\n align-items: flex-end;\n gap: ${v('space-4')};\n position: relative;\n padding: ${v('space-5')} ${v('space-6')};\n border-top: ${v('border-width')} solid ${v('border-primary')};\n background: ${v('bg-input')};\n}\n\n.${p}-input-wrapper {\n flex: 1;\n min-width: 0;\n position: relative;\n}\n\n.${p}-textarea {\n width: 100%;\n min-height: ${v('textarea-min-height')};\n max-height: ${v('textarea-max-height')};\n padding: ${v('space-4')} ${v('space-5')};\n overflow-y: auto;\n resize: none;\n outline: none;\n color: ${v('text-primary')};\n background: ${v('bg-primary')};\n border: ${v('border-width')} solid ${v('border-input')};\n border-radius: ${v('radius-md')};\n font-family: inherit;\n font-size: ${v('font-size')};\n line-height: ${v('line-height')};\n transition: border-color ${v('transition-fast')}, box-shadow ${v('transition-fast')};\n}\n\n.${p}-textarea:focus {\n border-color: ${v('border-input-focus')};\n box-shadow: 0 0 0 ${v('border-width-drop')} ${v('bg-drop-overlay')};\n}\n\n.${p}-textarea::placeholder {\n color: ${v('text-placeholder')};\n}\n\n.${p}-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${v('input-button-size')};\n height: ${v('input-button-size')};\n flex-shrink: 0;\n color: ${v('btn-primary-text')};\n background: ${v('btn-primary-bg')};\n border: 0;\n border-radius: ${v('radius-md')};\n cursor: pointer;\n transition: background ${v('transition-fast')}, opacity ${v('transition-fast')};\n}\n\n.${p}-send-btn:hover {\n background: ${v('btn-primary-hover')};\n}\n\n.${p}-send-btn:disabled {\n cursor: default;\n opacity: .5;\n}\n\n.${p}-send-btn svg {\n width: var(--size-7);\n height: var(--size-7);\n}\n\n.${p}-mention-panel {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 100%;\n z-index: ${v('z-mention')};\n max-height: ${v('panel-max-height')};\n margin-bottom: ${v('space-2')};\n overflow-y: auto;\n background: ${v('bg-mention')};\n border: ${v('border-width')} solid ${v('border-mention')};\n border-radius: ${v('radius-md')};\n box-shadow: ${v('shadow-mention')};\n}\n\n.${p}-mention-item {\n display: flex;\n align-items: center;\n gap: ${v('space-4')};\n padding: ${v('space-4')} ${v('space-5')};\n color: ${v('text-mention')};\n cursor: pointer;\n transition: background ${v('transition-fast')};\n}\n\n.${p}-mention-item:hover {\n background: ${v('bg-mention-hover')};\n}\n\n.${p}-mention-item--active {\n background: ${v('bg-mention-active')};\n}\n\n.${p}-mention-item-avatar {\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${v('mention-avatar-size')};\n height: ${v('mention-avatar-size')};\n flex-shrink: 0;\n overflow: hidden;\n color: ${v('avatar-text')};\n background: ${v('avatar-bg')};\n border-radius: ${v('radius-circle')};\n font-size: ${v('font-size-sm')};\n font-weight: ${v('font-weight-semibold')};\n}\n\n.${p}-mention-item-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.${p}-mention-item-name {\n font-size: ${v('font-size')};\n}\n\n.${p}-empty {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: ${v('text-secondary')};\n font-size: ${v('font-size')};\n}\n\n.${p}-toolbar {\n display: flex;\n align-items: center;\n gap: ${v('space-1')};\n padding: ${v('space-3')} ${v('space-4')};\n background: ${v('bg-toolbar')};\n border-bottom: ${v('border-width')} solid ${v('border-toolbar')};\n border-radius: ${v('radius-md')} ${v('radius-md')} 0 0;\n}\n\n.${p}-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${v('toolbar-button-size')};\n height: ${v('toolbar-button-size')};\n flex-shrink: 0;\n padding: 0;\n color: ${v('toolbar-icon-color')};\n background: unset;\n border: 0;\n border-radius: ${v('radius-sm')};\n cursor: pointer;\n transition: background ${v('transition-fast')}, color ${v('transition-fast')};\n}\n\n.${p}-toolbar-btn svg {\n width: var(--size-6);\n height: var(--size-6);\n}\n\n.${p}-toolbar-btn:hover {\n color: ${v('toolbar-icon-hover')};\n background: ${v('bg-drop-overlay')};\n}\n\n.${p}-toolbar-btn--active {\n color: ${v('toolbar-voice-active')};\n background: ${v('bg-danger-soft')};\n}\n\n.${p}-toolbar-btn--active:hover {\n color: ${v('toolbar-voice-active')};\n background: ${v('bg-danger-soft')};\n}\n\n.${p}-drop-overlay {\n position: absolute;\n inset: 0;\n z-index: ${v('z-overlay')};\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n background: ${v('bg-drop-overlay')};\n border: ${v('border-width-drop')} dashed ${v('toolbar-icon-hover')};\n border-radius: ${v('radius-md')};\n}\n\n.${p}-drop-overlay span {\n color: ${v('toolbar-icon-hover')};\n font-size: ${v('font-size-sm')};\n font-weight: ${v('font-weight-medium')};\n}\n\n@keyframes ${p}-blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0; }\n}\n\n.${p}-bubble--streaming::after {\n content: '';\n display: inline-block;\n width: ${v('border-width-drop')};\n height: 1em;\n margin-left: ${v('space-1')};\n vertical-align: text-bottom;\n background: currentColor;\n animation: ${p}-blink 800ms infinite;\n}\n`;\n}\n\nfunction v(name: string): string {\n return `var(${COMPONENT_CSS_VAR_PREFIX}-${name})`;\n}\n\nfunction toKebab(key: string): string {\n return key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\n}\n","/**\n * @composy/chat-core - 即时通讯/IM 组件核心库\n *\n * 提供聊天气泡、消息列表、@提及、多消息类型(文本/图片/文件/系统消息/自定义)、\n * 消息状态管理(发送中/已发送/已送达/已读/失败)、亮暗主题切换等能力。\n * 框架无关的核心实现,配合 Vue/React 适配层使用。\n *\n * @packageDocumentation\n * @module @composy/chat-core\n */\n\nimport type { ChatConfig, ChatInstance, ChatMessage, ThemeMode, MentionItem, ToolbarConfig } from './types';\nimport type { ThemeTokens } from './theme/tokens';\nimport { EventEmitter } from './core/event-emitter';\nimport { ChatManager } from './core/chat-manager';\nimport { MentionEngine } from './core/mention-engine';\nimport { ThemeManager } from './theme/theme-manager';\nimport { DOMRenderer } from './renderer/dom-renderer';\nimport { injectStyles, updateStyles, removeStyles } from './renderer/style-manager';\nimport { DEFAULT_CLASS_PREFIX, normalizeClassPrefix } from './constants/dom';\n\nexport const version = '0.1.0';\n\n// Types\nexport * from './types';\n\n// Core\nexport { EventEmitter } from './core/event-emitter';\nexport { ChatManager } from './core/chat-manager';\nexport { MentionEngine } from './core/mention-engine';\nexport type { MentionState } from './core/mention-engine';\n\n// Theme\nexport { ThemeManager } from './theme/theme-manager';\nexport type { ThemeTokens } from './theme/tokens';\nexport { lightTokens, darkTokens } from './theme/tokens';\n\n// Renderer\nexport { DOMRenderer } from './renderer/dom-renderer';\nexport { injectStyles, updateStyles, removeStyles, cls, clsx } from './renderer/style-manager';\nexport {\n DEFAULT_CLASS_PREFIX,\n COMPONENT_CSS_VAR_PREFIX,\n STYLE_ELEMENT_ID,\n getStyleElementId,\n normalizeClassPrefix,\n cx,\n} from './constants/dom';\n\n/**\n * 创建聊天实例\n */\nexport function createChat(config: ChatConfig): ChatInstance {\n // 解析容器\n const container =\n typeof config.container === 'string'\n ? document.querySelector<HTMLElement>(config.container)\n : config.container;\n\n if (!container) {\n throw new Error(`[Chat] Container not found: ${config.container}`);\n }\n\n const prefix = normalizeClassPrefix(config.classPrefix ?? DEFAULT_CLASS_PREFIX);\n const normalizedConfig = {\n ...config,\n classPrefix: prefix,\n };\n const emitter = new EventEmitter();\n const chatManager = new ChatManager(emitter, normalizedConfig.messages);\n const mentionEngine = new MentionEngine(emitter, normalizedConfig.mentionMembers);\n const themeManager = new ThemeManager(emitter, normalizedConfig.theme ?? 'light');\n const renderer = new DOMRenderer(container, normalizedConfig, emitter, mentionEngine);\n\n // 注入样式\n injectStyles(themeManager.getTokens(), prefix);\n\n // 初始化渲染\n renderer.init();\n renderer.renderMessages(chatManager.getMessages());\n\n // 初始滚动到底部\n requestAnimationFrame(() => {\n renderer.scrollToBottom(false);\n });\n\n // 监听主题变化\n emitter.on('theme-change', (_resolved: string, tokens: ThemeTokens) => {\n updateStyles(tokens, prefix);\n });\n\n // 监听消息变化\n emitter.on('message-added', (message: ChatMessage) => {\n renderer.appendMessage(message);\n requestAnimationFrame(() => {\n renderer.scrollToBottom(true);\n });\n });\n\n emitter.on('messages-prepended', (messages: ChatMessage[]) => {\n renderer.prependMessages(messages);\n });\n\n emitter.on('message-updated', (message: ChatMessage) => {\n renderer.updateMessage(message.id, message);\n });\n\n emitter.on('message-removed', (message: ChatMessage) => {\n renderer.removeMessage(message.id);\n });\n\n // 流式消息内容追加\n emitter.on('message-content-appended', (id: string, content: string) => {\n renderer.updateMessageContent(id, content);\n requestAnimationFrame(() => {\n renderer.scrollToBottom(false);\n });\n });\n\n // 创建实例\n const instance: ChatInstance = {\n addMessage(message: ChatMessage) {\n chatManager.addMessage(message);\n },\n\n prependMessages(messages: ChatMessage[]) {\n chatManager.prependMessages(messages);\n },\n\n updateMessage(id: string, updates: Partial<ChatMessage>) {\n chatManager.updateMessage(id, updates);\n },\n\n removeMessage(id: string) {\n chatManager.removeMessage(id);\n },\n\n setMessages(messages: ChatMessage[]) {\n chatManager.setMessages(messages);\n renderer.renderMessages(chatManager.getMessages());\n requestAnimationFrame(() => {\n renderer.scrollToBottom(false);\n });\n },\n\n clearMessages() {\n chatManager.clearMessages();\n renderer.renderMessages([]);\n },\n\n scrollToBottom(smooth = true) {\n renderer.scrollToBottom(smooth);\n },\n\n setTheme(theme: ThemeMode) {\n themeManager.setTheme(theme);\n },\n\n setMentionMembers(members: MentionItem[]) {\n mentionEngine.setMembers(members);\n },\n\n setLoadingMore(loading: boolean) {\n renderer.setLoadingMore(loading);\n },\n\n focusInput() {\n renderer.focusInput();\n },\n\n setInputContent(content: string) {\n renderer.setInputContent(content);\n },\n\n getInputContent() {\n return renderer.getInputContent();\n },\n\n clearInput() {\n renderer.clearInput();\n },\n\n isAtBottom(threshold?: number) {\n return renderer.isAtBottom(threshold);\n },\n\n on(event: string, handler: (...args: unknown[]) => void) {\n return emitter.on(event, handler);\n },\n\n getMessages() {\n return chatManager.getMessages();\n },\n\n getMessage(id: string) {\n return chatManager.getMessage(id);\n },\n\n appendMessageContent(id: string, chunk: string) {\n chatManager.appendMessageContent(id, chunk);\n },\n\n finishStreaming(id: string) {\n chatManager.finishStreaming(id);\n },\n\n destroy() {\n themeManager.destroy();\n renderer.destroy();\n emitter.removeAll();\n removeStyles(prefix);\n },\n };\n\n return instance;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.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, '"')\r\n .replace(/'/g, ''')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\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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"}
|