ai-chat-ui-kit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/.eslintrc.cjs +74 -0
  2. package/.github/actions/screenshot/action.yml +35 -0
  3. package/.github/workflows/pages.yml +46 -0
  4. package/README.md +285 -0
  5. package/docs/README.md +176 -0
  6. package/docs/api/components.md +344 -0
  7. package/docs/api/core.md +349 -0
  8. package/docs/chat-style-1-minimal.html +78 -0
  9. package/docs/chat-style-2-neon.html +74 -0
  10. package/docs/chat-style-3-glass.html +73 -0
  11. package/docs/chat-style-4-terminal.html +84 -0
  12. package/docs/chat-style-5-gradient.html +69 -0
  13. package/docs/chat-style-6-corporate.html +116 -0
  14. package/docs/examples/basic-chat.md +291 -0
  15. package/docs/examples/custom-plugins.md +431 -0
  16. package/docs/examples/multi-model.md +466 -0
  17. package/docs/guide/api-adapters.md +431 -0
  18. package/docs/guide/getting-started.md +244 -0
  19. package/docs/guide/headless-mode.md +508 -0
  20. package/docs/guide/plugins.md +416 -0
  21. package/docs/guide/themes.md +327 -0
  22. package/docs/index.html +256 -0
  23. package/docs/theme-preview-1-minimal.html +74 -0
  24. package/docs/theme-preview-2-neon.html +73 -0
  25. package/docs/theme-preview-3-glass.html +77 -0
  26. package/docs/theme-preview-4-terminal.html +86 -0
  27. package/docs/theme-preview-5-gradient.html +79 -0
  28. package/docs/theme-preview-6-corporate.html +71 -0
  29. package/examples/index.html +414 -0
  30. package/examples/react-app/App.tsx +131 -0
  31. package/examples/react-app/index.html +12 -0
  32. package/examples/react-app/main.tsx +15 -0
  33. package/examples/react-app/package.json +24 -0
  34. package/examples/vue-app/index.html +12 -0
  35. package/examples/vue-app/package.json +22 -0
  36. package/examples/vue-app/src/App.vue +145 -0
  37. package/examples/vue-app/src/main.ts +9 -0
  38. package/package.json +44 -0
  39. package/packages/components/package.json +25 -0
  40. package/packages/components/src/chat/chat.css +80 -0
  41. package/packages/components/src/chat/chat.ts +236 -0
  42. package/packages/components/src/index.ts +36 -0
  43. package/packages/components/src/input/input.css +52 -0
  44. package/packages/components/src/input/input.ts +116 -0
  45. package/packages/components/src/markdown/markdown.css +118 -0
  46. package/packages/components/src/markdown/markdown.ts +229 -0
  47. package/packages/components/src/message/message.css +56 -0
  48. package/packages/components/src/message/message.ts +72 -0
  49. package/packages/components/src/styles/global.css +43 -0
  50. package/packages/components/src/tool-call/tool-call.css +98 -0
  51. package/packages/components/src/tool-call/tool-call.ts +171 -0
  52. package/packages/components/src/types.ts +55 -0
  53. package/packages/components/src/utils/helpers.ts +128 -0
  54. package/packages/components/tsconfig.json +25 -0
  55. package/packages/components/tsup.config.ts +18 -0
  56. package/packages/core/package.json +47 -0
  57. package/packages/core/pnpm-lock.yaml +2032 -0
  58. package/packages/core/pnpm-workspace.yaml +2 -0
  59. package/packages/core/src/api/adapters.ts +717 -0
  60. package/packages/core/src/api/base.ts +210 -0
  61. package/packages/core/src/api/index.ts +54 -0
  62. package/packages/core/src/index.ts +93 -0
  63. package/packages/core/src/parser/latex.ts +274 -0
  64. package/packages/core/src/parser/markdown.test.ts +58 -0
  65. package/packages/core/src/parser/markdown.ts +206 -0
  66. package/packages/core/src/parser/mermaid.ts +276 -0
  67. package/packages/core/src/plugins/PluginManager.ts +232 -0
  68. package/packages/core/src/plugins/builtin.ts +406 -0
  69. package/packages/core/src/store/ChatStore.ts +163 -0
  70. package/packages/core/src/store/ModelConfigStore.ts +136 -0
  71. package/packages/core/src/store/ToolCallStore.ts +164 -0
  72. package/packages/core/src/store/base.ts +75 -0
  73. package/packages/core/src/types/index.ts +133 -0
  74. package/packages/core/tsup.config.ts +18 -0
  75. package/packages/themes/package.json +33 -0
  76. package/packages/themes/src/corporate/index.ts +52 -0
  77. package/packages/themes/src/corporate/theme.css +228 -0
  78. package/packages/themes/src/glass/index.ts +52 -0
  79. package/packages/themes/src/glass/theme.css +237 -0
  80. package/packages/themes/src/gradient/index.ts +53 -0
  81. package/packages/themes/src/gradient/theme.css +218 -0
  82. package/packages/themes/src/index.ts +13 -0
  83. package/packages/themes/src/minimal/index.ts +52 -0
  84. package/packages/themes/src/minimal/theme.css +198 -0
  85. package/packages/themes/src/neon/index.ts +52 -0
  86. package/packages/themes/src/neon/theme.css +233 -0
  87. package/packages/themes/src/terminal/index.ts +52 -0
  88. package/packages/themes/src/terminal/theme.css +235 -0
  89. package/packages/themes/src/types.ts +10 -0
  90. package/packages/themes/src/vite-env.d.ts +9 -0
  91. package/packages/themes/tsup.config.ts +21 -0
  92. package/pnpm-workspace.yaml +4 -0
  93. package/tsconfig.json +27 -0
  94. package/vite.config.ts +25 -0
  95. package/vitest.config.ts +28 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ import { BaseStore } from './base.js';
7
+ import { ToolCall } from '../types/index.js';
8
+
9
+ // 工具调用状态
10
+ interface ToolCallState {
11
+ // 所有工具调用
12
+ toolCalls: Map<string, ToolCall>;
13
+ // 按消息 ID 索引
14
+ messageToolCalls: Map<string, string[]>;
15
+ // 正在执行的工具调用 ID
16
+ executingIds: Set<string>;
17
+ }
18
+
19
+ // 初始状态
20
+ const initialState: ToolCallState = {
21
+ toolCalls: new Map(),
22
+ messageToolCalls: new Map(),
23
+ executingIds: new Set()
24
+ };
25
+
26
+ export class ToolCallStore extends BaseStore<ToolCallState> {
27
+ constructor() {
28
+ super(initialState);
29
+ }
30
+
31
+ // 添加工具调用
32
+ addToolCall(messageId: string, toolCall: ToolCall): void {
33
+ const toolCalls = new Map(this.state.toolCalls);
34
+ toolCalls.set(toolCall.id, toolCall);
35
+
36
+ const messageToolCalls = new Map(this.state.messageToolCalls);
37
+ const ids = messageToolCalls.get(messageId) || [];
38
+ messageToolCalls.set(messageId, [...ids, toolCall.id]);
39
+
40
+ this.setState({ toolCalls, messageToolCalls });
41
+ }
42
+
43
+ // 批量添加工具调用
44
+ addToolCalls(messageId: string, toolCalls: ToolCall[]): void {
45
+ const newToolCalls = new Map(this.state.toolCalls);
46
+ const newMessageToolCalls = new Map(this.state.messageToolCalls);
47
+
48
+ const ids = newMessageToolCalls.get(messageId) || [];
49
+ const newIds: string[] = [];
50
+
51
+ toolCalls.forEach(tc => {
52
+ newToolCalls.set(tc.id, tc);
53
+ newIds.push(tc.id);
54
+ });
55
+
56
+ newMessageToolCalls.set(messageId, [...ids, ...newIds]);
57
+
58
+ this.setState({
59
+ toolCalls: newToolCalls,
60
+ messageToolCalls: newMessageToolCalls
61
+ });
62
+ }
63
+
64
+ // 更新工具调用状态
65
+ updateToolCallStatus(id: string, status: ToolCall['status']): void {
66
+ const toolCalls = new Map(this.state.toolCalls);
67
+ const toolCall = toolCalls.get(id);
68
+
69
+ if (toolCall) {
70
+ toolCalls.set(id, { ...toolCall, status });
71
+
72
+ const executingIds = new Set(this.state.executingIds);
73
+ if (status === 'executing') {
74
+ executingIds.add(id);
75
+ } else {
76
+ executingIds.delete(id);
77
+ }
78
+
79
+ this.setState({ toolCalls, executingIds });
80
+ }
81
+ }
82
+
83
+ // 设置工具调用结果
84
+ setToolCallResult(id: string, result: unknown): void {
85
+ const toolCalls = new Map(this.state.toolCalls);
86
+ const toolCall = toolCalls.get(id);
87
+
88
+ if (toolCall) {
89
+ toolCalls.set(id, { ...toolCall, result, status: 'completed' });
90
+
91
+ const executingIds = new Set(this.state.executingIds);
92
+ executingIds.delete(id);
93
+
94
+ this.setState({ toolCalls, executingIds });
95
+ }
96
+ }
97
+
98
+ // 设置工具调用错误
99
+ setToolCallError(id: string, error: unknown): void {
100
+ const toolCalls = new Map(this.state.toolCalls);
101
+ const toolCall = toolCalls.get(id);
102
+
103
+ if (toolCall) {
104
+ toolCalls.set(id, {
105
+ ...toolCall,
106
+ result: error,
107
+ status: 'failed'
108
+ });
109
+
110
+ const executingIds = new Set(this.state.executingIds);
111
+ executingIds.delete(id);
112
+
113
+ this.setState({ toolCalls, executingIds });
114
+ }
115
+ }
116
+
117
+ // 获取消息的工具调用
118
+ getToolCallsForMessage(messageId: string): ToolCall[] {
119
+ const ids = this.state.messageToolCalls.get(messageId) || [];
120
+ return ids
121
+ .map(id => this.state.toolCalls.get(id))
122
+ .filter(Boolean) as ToolCall[];
123
+ }
124
+
125
+ // 获取正在执行的工具调用
126
+ getExecutingToolCalls(): ToolCall[] {
127
+ return Array.from(this.state.executingIds)
128
+ .map(id => this.state.toolCalls.get(id))
129
+ .filter(Boolean) as ToolCall[];
130
+ }
131
+
132
+ // 是否有正在执行的工具调用
133
+ hasExecuting(): boolean {
134
+ return this.state.executingIds.size > 0;
135
+ }
136
+
137
+ // 清除消息的工具调用
138
+ clearToolCallsForMessage(messageId: string): void {
139
+ const messageToolCalls = new Map(this.state.messageToolCalls);
140
+ const ids = messageToolCalls.get(messageId) || [];
141
+
142
+ const toolCalls = new Map(this.state.toolCalls);
143
+ const executingIds = new Set(this.state.executingIds);
144
+
145
+ ids.forEach(id => {
146
+ toolCalls.delete(id);
147
+ executingIds.delete(id);
148
+ });
149
+
150
+ messageToolCalls.delete(messageId);
151
+
152
+ this.setState({ toolCalls, messageToolCalls, executingIds });
153
+ }
154
+
155
+ // 清除所有工具调用
156
+ clearAll(): void {
157
+ this.setState(initialState);
158
+ }
159
+
160
+ // 重置
161
+ reset(): void {
162
+ this.setState(initialState);
163
+ }
164
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ // 简单的事件发射器(用于状态管理)
7
+ export class EventEmitter {
8
+ private events: Map<string, Set<Function>> = new Map();
9
+
10
+ // 订阅事件
11
+ on(event: string, callback: Function): void {
12
+ if (!this.events.has(event)) {
13
+ this.events.set(event, new Set());
14
+ }
15
+ this.events.get(event)?.add(callback);
16
+ }
17
+
18
+ // 取消订阅
19
+ off(event: string, callback: Function): void {
20
+ const callbacks = this.events.get(event);
21
+ if (callbacks) {
22
+ callbacks.delete(callback);
23
+ }
24
+ }
25
+
26
+ // 触发事件
27
+ emit(event: string, ...args: unknown[]): void {
28
+ const callbacks = this.events.get(event);
29
+ if (callbacks) {
30
+ callbacks.forEach((callback) => {
31
+ try {
32
+ callback(...args);
33
+ } catch (error) {
34
+ console.error(`Error in event listener for "${event}":`, error);
35
+ }
36
+ });
37
+ }
38
+ }
39
+
40
+ // 清空所有事件
41
+ clear(): void {
42
+ this.events.clear();
43
+ }
44
+ }
45
+
46
+ // Store 基类
47
+ export abstract class BaseStore<T> {
48
+ protected state: T;
49
+ protected emitter: EventEmitter;
50
+
51
+ constructor(initialState: T) {
52
+ this.state = initialState;
53
+ this.emitter = new EventEmitter();
54
+ }
55
+
56
+ // 获取状态
57
+ getState(): T {
58
+ return this.state;
59
+ }
60
+
61
+ // 更新状态
62
+ protected setState(partial: Partial<T>): void {
63
+ this.state = { ...this.state, ...partial };
64
+ this.emitter.emit('change', this.state);
65
+ }
66
+
67
+ // 订阅状态变化
68
+ subscribe(callback: (state: T) => void): () => void {
69
+ this.emitter.on('change', callback);
70
+ return () => this.emitter.off('change', callback);
71
+ }
72
+
73
+ // 重置状态
74
+ abstract reset(): void;
75
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ // 消息角色枚举
7
+ export enum MessageRole {
8
+ User = 'user',
9
+ Assistant = 'assistant',
10
+ System = 'system',
11
+ Tool = 'tool'
12
+ }
13
+
14
+ // 消息类型
15
+ export interface Message {
16
+ id: string;
17
+ role: MessageRole;
18
+ content: string;
19
+ timestamp: number;
20
+ // 工具调用相关
21
+ toolCalls?: ToolCall[];
22
+ // 元数据(用于插件扩展)
23
+ metadata?: Record<string, unknown>;
24
+ }
25
+
26
+ // 工具调用
27
+ export interface ToolCall {
28
+ id: string;
29
+ name: string;
30
+ arguments: Record<string, unknown>;
31
+ result?: unknown;
32
+ status: 'pending' | 'executing' | 'completed' | 'failed';
33
+ }
34
+
35
+ // 模型配置
36
+ export interface ModelConfig {
37
+ // 模型提供商
38
+ provider: 'openai' | 'ernie' | 'qwen' | 'spark' | 'hunyuan' | 'custom';
39
+ // 模型名称
40
+ model: string;
41
+ // API 端点
42
+ apiEndpoint?: string;
43
+ // API Key
44
+ apiKey?: string;
45
+ // 自定义请求头
46
+ headers?: Record<string, string>;
47
+ // 请求参数
48
+ params?: {
49
+ temperature?: number;
50
+ topP?: number;
51
+ maxTokens?: number;
52
+ [key: string]: unknown;
53
+ };
54
+ }
55
+
56
+ // 聊天配置
57
+ export interface ChatConfig {
58
+ // 是否启用流式输出
59
+ stream?: boolean;
60
+ // 系统提示词
61
+ systemPrompt?: string;
62
+ // 历史消息数量限制
63
+ maxHistory?: number;
64
+ // 是否启用工具调用
65
+ enableTools?: boolean;
66
+ }
67
+
68
+ // API 适配器接口
69
+ export interface APIAdapter {
70
+ // 发送消息
71
+ sendMessage(params: {
72
+ messages: Message[];
73
+ modelConfig: ModelConfig;
74
+ chatConfig: ChatConfig;
75
+ onChunk?: (chunk: string) => void;
76
+ onToolCall?: (toolCall: ToolCall) => void;
77
+ onComplete?: (message: Message) => void;
78
+ onError?: (error: Error) => void;
79
+ }): Promise<void>;
80
+
81
+ // 取消请求
82
+ abort(): void;
83
+ }
84
+
85
+ // 消息插件接口
86
+ export interface MessagePlugin {
87
+ // 插件类型标识
88
+ type: string;
89
+ // 判断是否匹配该插件
90
+ match: (content: string) => boolean;
91
+ // 渲染函数
92
+ render: (content: string, context: RenderContext) => HTMLElement | string;
93
+ // 优先级(数字越大优先级越高)
94
+ priority?: number;
95
+ }
96
+
97
+ // 渲染上下文
98
+ export interface RenderContext {
99
+ // 消息对象
100
+ message: Message;
101
+ // 是否流式输出中
102
+ isStreaming: boolean;
103
+ // 主题
104
+ theme: string;
105
+ // 自定义配置
106
+ [key: string]: unknown;
107
+ }
108
+
109
+ // 主题配置
110
+ export interface ThemeConfig {
111
+ // 主题名称
112
+ name: string;
113
+ // CSS 变量
114
+ variables: Record<string, string>;
115
+ // 自定义样式
116
+ styles?: string;
117
+ }
118
+
119
+ // 聊天状态
120
+ export interface ChatState {
121
+ // 消息列表
122
+ messages: Message[];
123
+ // 是否加载中
124
+ isLoading: boolean;
125
+ // 是否流式输出中
126
+ isStreaming: boolean;
127
+ // 错误
128
+ error: Error | null;
129
+ // 当前会话 ID
130
+ sessionId: string;
131
+ }
132
+
133
+
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+ import { defineConfig } from 'tsup';
6
+
7
+ export default defineConfig({
8
+ entry: ['src/**/*.ts'],
9
+ outDir: 'dist',
10
+ format: ['esm', 'cjs'],
11
+ target: 'es2020',
12
+ splitting: true,
13
+ clean: true,
14
+ dts: true,
15
+ sourcemap: true,
16
+ treeshake: true,
17
+ external: ['vitest', 'vitest/**'],
18
+ });
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@ai-chat/themes",
3
+ "version": "0.1.0",
4
+ "description": "Theme packages for AI Chat UI Kit",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.mts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.mts"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": ["dist"],
17
+ "scripts": {
18
+ "dev": "tsup --watch",
19
+ "build": "tsup"
20
+ },
21
+ "dependencies": {},
22
+ "devDependencies": {
23
+ "copyfiles": "^2.0.0"
24
+ },
25
+ "peerDependenciesMeta": {
26
+ "@ai-chat/components": {
27
+ "optional": true
28
+ }
29
+ },
30
+ "keywords": ["ai", "chat", "theme", "ui"],
31
+ "author": "edenxpzhang",
32
+ "license": "MIT"
33
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ import type { ThemeConfig } from '../types.js';
7
+ import themeStyles from './theme.css?raw';
8
+
9
+ export const corporateTheme: ThemeConfig = {
10
+ name: 'corporate',
11
+ variables: {
12
+ '--ai-primary': '#1890ff',
13
+ '--ai-primary-hover': '#40a9ff',
14
+ '--ai-primary-active': '#096dd9',
15
+ '--ai-bg-primary': '#ffffff',
16
+ '--ai-bg-secondary': '#fafafa',
17
+ '--ai-bg-tertiary': '#f0f2f5',
18
+ '--ai-bg-chat': '#fafafa',
19
+ '--ai-text-primary': '#333333',
20
+ '--ai-text-secondary': '#666666',
21
+ '--ai-text-tertiary': '#999999',
22
+ '--ai-text-inverse': '#ffffff',
23
+ '--ai-message-user-bg': '#1890ff',
24
+ '--ai-message-user-text': '#ffffff',
25
+ '--ai-message-ai-bg': '#ffffff',
26
+ '--ai-message-ai-text': '#333333',
27
+ '--ai-message-border': '#e8e8e8',
28
+ '--ai-input-bg': '#ffffff',
29
+ '--ai-input-border': '#d9d9d9',
30
+ '--ai-input-focus-border': '#1890ff',
31
+ '--ai-input-text': '#333333',
32
+ '--ai-input-placeholder': '#999999',
33
+ '--ai-tool-call-bg': '#f6f8fa',
34
+ '--ai-tool-call-border': '#d1d9e0',
35
+ '--ai-tool-call-success': '#52c41a',
36
+ '--ai-tool-call-error': '#ff4d4f',
37
+ '--ai-tool-call-running': '#1890ff',
38
+ '--ai-shadow-sm': '0 1px 2px rgba(0, 0, 0, 0.06)',
39
+ '--ai-shadow-md': '0 2px 8px rgba(0, 0, 0, 0.1)',
40
+ '--ai-shadow-lg': '0 2px 8px rgba(0, 0, 0, 0.1)',
41
+ '--ai-radius-sm': '2px',
42
+ '--ai-radius-md': '4px',
43
+ '--ai-radius-lg': '8px',
44
+ '--ai-radius-xl': '8px',
45
+ '--ai-spacing-xs': '4px',
46
+ '--ai-spacing-sm': '8px',
47
+ '--ai-spacing-md': '12px',
48
+ '--ai-spacing-lg': '24px',
49
+ '--ai-spacing-xl': '24px',
50
+ },
51
+ styles: themeStyles,
52
+ };
@@ -0,0 +1,228 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ *
5
+ * Corporate Professional —— 企业商务
6
+ * 对齐 docs/chat-style-6-corporate.html
7
+ */
8
+
9
+ :root[data-theme='corporate'],
10
+ .ai-theme-corporate {
11
+ --ai-primary: #1890ff;
12
+ --ai-primary-hover: #40a9ff;
13
+ --ai-bg-primary: #ffffff;
14
+ --ai-bg-secondary: #fafafa;
15
+ --ai-text-primary: #333;
16
+ --ai-border: #e8e8e8;
17
+ --ai-message-user-bg: #1890ff;
18
+ --ai-message-user-text: #fff;
19
+ --ai-message-ai-bg: #fff;
20
+ --ai-message-ai-text: #333;
21
+ }
22
+
23
+ /* body */
24
+ .ai-theme-corporate-host,
25
+ body[data-theme='corporate'] {
26
+ background: #f0f2f5;
27
+ }
28
+
29
+ /* 容器 */
30
+ .ai-theme-corporate .ai-chat,
31
+ [data-theme='corporate'] .ai-chat {
32
+ background: #fff;
33
+ border-radius: 8px;
34
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
35
+ border: 1px solid #e8e8e8;
36
+ font-family: 'Microsoft YaHei', 'Segoe UI', sans-serif;
37
+ overflow: hidden;
38
+ }
39
+
40
+ /* Header */
41
+ .ai-theme-corporate .ai-chat__header,
42
+ [data-theme='corporate'] .ai-chat__header {
43
+ padding: 16px 24px;
44
+ background: #fff;
45
+ border-bottom: 3px solid #1890ff;
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 16px;
49
+ }
50
+ .ai-theme-corporate .ai-chat__avatar,
51
+ [data-theme='corporate'] .ai-chat__avatar {
52
+ width: 42px;
53
+ height: 42px;
54
+ background: #1890ff;
55
+ border-radius: 8px;
56
+ color: #fff;
57
+ font-size: 18px;
58
+ font-weight: bold;
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ }
63
+ .ai-theme-corporate .ai-chat__title,
64
+ [data-theme='corporate'] .ai-chat__title {
65
+ font-size: 16px;
66
+ font-weight: 600;
67
+ color: #333;
68
+ }
69
+ .ai-theme-corporate .ai-chat__subtitle,
70
+ [data-theme='corporate'] .ai-chat__subtitle {
71
+ font-size: 12px;
72
+ color: #999;
73
+ }
74
+
75
+ /* Messages */
76
+ .ai-theme-corporate .ai-chat__messages,
77
+ [data-theme='corporate'] .ai-chat__messages {
78
+ background: #fafafa;
79
+ padding: 24px;
80
+ gap: 20px;
81
+ }
82
+ .ai-theme-corporate .ai-chat__messages::-webkit-scrollbar,
83
+ [data-theme='corporate'] .ai-chat__messages::-webkit-scrollbar { width: 6px; }
84
+ .ai-theme-corporate .ai-chat__messages::-webkit-scrollbar-thumb,
85
+ [data-theme='corporate'] .ai-chat__messages::-webkit-scrollbar-thumb {
86
+ background: #d9d9d9;
87
+ border-radius: 3px;
88
+ }
89
+
90
+ /* Message */
91
+ .ai-theme-corporate .ai-message,
92
+ [data-theme='corporate'] .ai-message {
93
+ max-width: 85%;
94
+ display: flex;
95
+ gap: 12px;
96
+ }
97
+ .ai-theme-corporate .ai-message__avatar,
98
+ [data-theme='corporate'] .ai-message__avatar {
99
+ display: flex;
100
+ width: 36px;
101
+ height: 36px;
102
+ border-radius: 50%;
103
+ align-items: center;
104
+ justify-content: center;
105
+ font-size: 13px;
106
+ font-weight: bold;
107
+ color: #fff;
108
+ flex-shrink: 0;
109
+ }
110
+ .ai-theme-corporate .ai-message--user .ai-message__avatar,
111
+ [data-theme='corporate'] .ai-message--user .ai-message__avatar { background: #52c41a; }
112
+ .ai-theme-corporate .ai-message--assistant .ai-message__avatar,
113
+ [data-theme='corporate'] .ai-message--assistant .ai-message__avatar { background: #1890ff; }
114
+ .ai-theme-corporate .ai-message__content,
115
+ [data-theme='corporate'] .ai-message__content {
116
+ padding: 12px 16px;
117
+ border-radius: 8px;
118
+ font-size: 14px;
119
+ line-height: 1.6;
120
+ }
121
+ .ai-theme-corporate .ai-message--user .ai-message__content,
122
+ [data-theme='corporate'] .ai-message--user .ai-message__content {
123
+ background: #1890ff;
124
+ color: #fff;
125
+ border-top-right-radius: 2px;
126
+ }
127
+ .ai-theme-corporate .ai-message--assistant .ai-message__content,
128
+ [data-theme='corporate'] .ai-message--assistant .ai-message__content {
129
+ background: #fff;
130
+ color: #333;
131
+ border: 1px solid #e8e8e8;
132
+ border-top-left-radius: 2px;
133
+ }
134
+ .ai-theme-corporate .ai-message__time,
135
+ [data-theme='corporate'] .ai-message__time {
136
+ font-size: 11px;
137
+ color: #999;
138
+ margin-top: 4px;
139
+ }
140
+ .ai-theme-corporate .ai-message--user .ai-message__time,
141
+ [data-theme='corporate'] .ai-message--user .ai-message__time { text-align: right; }
142
+
143
+ /* Input */
144
+ .ai-theme-corporate .ai-input,
145
+ [data-theme='corporate'] .ai-input {
146
+ padding: 16px 24px;
147
+ background: #fff;
148
+ border-top: 1px solid #e8e8e8;
149
+ }
150
+ .ai-theme-corporate .ai-input__wrapper,
151
+ [data-theme='corporate'] .ai-input__wrapper {
152
+ display: flex;
153
+ gap: 12px;
154
+ align-items: flex-end;
155
+ }
156
+ .ai-theme-corporate .ai-input__textarea,
157
+ [data-theme='corporate'] .ai-input__textarea {
158
+ flex: 1;
159
+ padding: 12px 16px;
160
+ border: 1px solid #d9d9d9;
161
+ border-radius: 6px;
162
+ font-size: 14px;
163
+ resize: none;
164
+ outline: none;
165
+ min-height: 44px;
166
+ max-height: 120px;
167
+ font-family: inherit;
168
+ transition: all 0.2s;
169
+ background: #fff;
170
+ color: #333;
171
+ }
172
+ .ai-theme-corporate .ai-input__textarea:focus,
173
+ [data-theme='corporate'] .ai-input__textarea:focus {
174
+ border-color: #1890ff;
175
+ box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
176
+ }
177
+ .ai-theme-corporate .ai-input__send,
178
+ [data-theme='corporate'] .ai-input__send {
179
+ padding: 12px 24px;
180
+ background: #1890ff;
181
+ color: #fff;
182
+ border: none;
183
+ border-radius: 6px;
184
+ cursor: pointer;
185
+ font-size: 14px;
186
+ font-weight: 500;
187
+ transition: all 0.2s;
188
+ white-space: nowrap;
189
+ }
190
+ .ai-theme-corporate .ai-input__send:hover:not(:disabled),
191
+ [data-theme='corporate'] .ai-input__send:hover:not(:disabled) {
192
+ background: #40a9ff;
193
+ }
194
+ .ai-theme-corporate .ai-input__send:disabled,
195
+ [data-theme='corporate'] .ai-input__send:disabled {
196
+ background: #d9d9d9;
197
+ cursor: not-allowed;
198
+ }
199
+
200
+ /* Typing */
201
+ .ai-theme-corporate .ai-typing-indicator,
202
+ [data-theme='corporate'] .ai-typing-indicator {
203
+ display: flex;
204
+ gap: 4px;
205
+ padding: 14px 16px;
206
+ background: #fff;
207
+ border: 1px solid #e8e8e8;
208
+ border-radius: 8px;
209
+ border-top-left-radius: 2px;
210
+ width: fit-content;
211
+ }
212
+ .ai-theme-corporate .ai-typing-indicator__dot,
213
+ [data-theme='corporate'] .ai-typing-indicator__dot {
214
+ width: 6px;
215
+ height: 6px;
216
+ background: #999;
217
+ border-radius: 50%;
218
+ animation: ai-typing-bounce 1.4s infinite;
219
+ }
220
+ .ai-theme-corporate .ai-typing-indicator__dot:nth-child(2),
221
+ [data-theme='corporate'] .ai-typing-indicator__dot:nth-child(2) { animation-delay: 0.2s; }
222
+ .ai-theme-corporate .ai-typing-indicator__dot:nth-child(3),
223
+ [data-theme='corporate'] .ai-typing-indicator__dot:nth-child(3) { animation-delay: 0.4s; }
224
+
225
+ @keyframes ai-typing-bounce {
226
+ 0%, 60%, 100% { transform: translateY(0); }
227
+ 30% { transform: translateY(-6px); }
228
+ }