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,116 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ import { LitElement, html } from 'lit';
7
+ import { customElement, property, state } from 'lit/decorators.js';
8
+ import './input.css';
9
+
10
+ @customElement('ai-input')
11
+ export class AiInput extends LitElement {
12
+ @property({ type: Boolean })
13
+ headless = true;
14
+
15
+ @property({ type: Boolean })
16
+ disabled = false;
17
+
18
+ @property({ type: String })
19
+ placeholder = '输入消息...';
20
+
21
+ @property({ type: String, attribute: 'send-text' })
22
+ sendText = '发送';
23
+
24
+ @state()
25
+ private value = '';
26
+
27
+ private textarea?: HTMLTextAreaElement;
28
+
29
+ // 默认 light DOM
30
+ createRenderRoot() {
31
+ if (this.headless) {
32
+ return this;
33
+ }
34
+ return super.createRenderRoot();
35
+ }
36
+
37
+ firstUpdated() {
38
+ this.textarea = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement;
39
+ }
40
+
41
+ render() {
42
+ return html`
43
+ <div class="ai-input">
44
+ <div class="ai-input__wrapper">
45
+ <textarea
46
+ class="ai-input__textarea"
47
+ .value=${this.value}
48
+ placeholder=${this.placeholder}
49
+ ?disabled=${this.disabled}
50
+ @input=${this.handleInput}
51
+ @keydown=${this.handleKeyDown}
52
+ rows="1"
53
+ ></textarea>
54
+ <button
55
+ class="ai-input__send"
56
+ ?disabled=${this.disabled || !this.value.trim()}
57
+ @click=${this.handleSend}
58
+ >
59
+ ${this.sendText}
60
+ </button>
61
+ </div>
62
+ </div>
63
+ `;
64
+ }
65
+
66
+ private handleInput(e: Event) {
67
+ const target = e.target as HTMLTextAreaElement;
68
+ this.value = target.value;
69
+ this.adjustHeight(target);
70
+
71
+ this.dispatchEvent(
72
+ new CustomEvent('input-change', {
73
+ detail: { value: this.value },
74
+ bubbles: true,
75
+ composed: true,
76
+ })
77
+ );
78
+ }
79
+
80
+ private handleKeyDown(e: KeyboardEvent) {
81
+ if (e.key === 'Enter' && !e.shiftKey) {
82
+ e.preventDefault();
83
+ this.handleSend();
84
+ }
85
+ }
86
+
87
+ private handleSend() {
88
+ if (!this.value.trim() || this.disabled) return;
89
+
90
+ this.dispatchEvent(
91
+ new CustomEvent('send', {
92
+ detail: { content: this.value },
93
+ bubbles: true,
94
+ composed: true,
95
+ })
96
+ );
97
+
98
+ this.value = '';
99
+ if (this.textarea) {
100
+ this.textarea.style.height = 'auto';
101
+ }
102
+ }
103
+
104
+ private adjustHeight(textarea: HTMLTextAreaElement) {
105
+ textarea.style.height = 'auto';
106
+ const maxHeight = 120;
107
+ const newHeight = Math.min(textarea.scrollHeight, maxHeight);
108
+ textarea.style.height = `${newHeight}px`;
109
+ }
110
+ }
111
+
112
+ declare global {
113
+ interface HTMLElementTagNameMap {
114
+ 'ai-input': AiInput;
115
+ }
116
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+ :host {
6
+ display: block;
7
+ }
8
+
9
+ .markdown-content {
10
+ line-height: 1.6;
11
+ }
12
+
13
+ .markdown-content h1 {
14
+ font-size: 2em;
15
+ margin: 0.67em 0;
16
+ font-weight: 600;
17
+ }
18
+
19
+ .markdown-content h2 {
20
+ font-size: 1.5em;
21
+ margin: 0.83em 0;
22
+ font-weight: 600;
23
+ }
24
+
25
+ .markdown-content h3 {
26
+ font-size: 1.17em;
27
+ margin: 1em 0;
28
+ font-weight: 600;
29
+ }
30
+
31
+ .markdown-content p {
32
+ margin: 0.5em 0;
33
+ }
34
+
35
+ .markdown-content code {
36
+ background-color: var(--ai-bg-secondary, #f5f5f5);
37
+ padding: 2px 6px;
38
+ border-radius: 4px;
39
+ font-family: 'Courier New', monospace;
40
+ font-size: 0.9em;
41
+ }
42
+
43
+ .markdown-content pre {
44
+ background-color: var(--ai-bg-secondary, #f5f5f5);
45
+ padding: 12px;
46
+ border-radius: var(--ai-border-radius, 8px);
47
+ overflow-x: auto;
48
+ margin: 0.5em 0;
49
+ }
50
+
51
+ .markdown-content pre code {
52
+ background-color: transparent;
53
+ padding: 0;
54
+ }
55
+
56
+ .markdown-content blockquote {
57
+ border-left: 4px solid var(--ai-border, #e8e8e8);
58
+ padding-left: 12px;
59
+ margin: 0.5em 0;
60
+ color: var(--ai-text-secondary, #666666);
61
+ }
62
+
63
+ .markdown-content ul,
64
+ .markdown-content ol {
65
+ padding-left: 2em;
66
+ margin: 0.5em 0;
67
+ }
68
+
69
+ .markdown-content a {
70
+ color: var(--ai-primary, #1677ff);
71
+ text-decoration: none;
72
+ }
73
+
74
+ .markdown-content a:hover {
75
+ text-decoration: underline;
76
+ }
77
+
78
+ .markdown-content table {
79
+ border-collapse: collapse;
80
+ width: 100%;
81
+ margin: 0.5em 0;
82
+ }
83
+
84
+ .markdown-content th,
85
+ .markdown-content td {
86
+ border: 1px solid var(--ai-border, #e8e8e8);
87
+ padding: 8px 12px;
88
+ text-align: left;
89
+ }
90
+
91
+ .markdown-content th {
92
+ background-color: var(--ai-bg-secondary, #f5f5f5);
93
+ font-weight: 600;
94
+ }
95
+
96
+ /* Mermaid 图表容器 */
97
+ .mermaid-container {
98
+ margin: 1em 0;
99
+ padding: 12px;
100
+ background-color: var(--ai-bg, #ffffff);
101
+ border: 1px solid var(--ai-border, #e8e8e8);
102
+ border-radius: var(--ai-border-radius, 8px);
103
+ overflow-x: auto;
104
+ text-align: center;
105
+ }
106
+
107
+ /* Latex 公式 */
108
+ .latex-formula {
109
+ font-style: italic;
110
+ padding: 0 4px;
111
+ }
112
+
113
+ .latex-block {
114
+ display: block;
115
+ text-align: center;
116
+ margin: 1em 0;
117
+ font-size: 1.2em;
118
+ }
@@ -0,0 +1,229 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ import { LitElement, html, css } from 'lit';
7
+ import { customElement, property } from 'lit/decorators.js';
8
+ import './markdown.css';
9
+
10
+ // 简单的 Markdown 解析器(等待 core 包完成后替换为实际导入)
11
+ function parseMarkdown(content: string): string {
12
+ let html = content;
13
+
14
+ // 代码块
15
+ html = html.replace(/```(\w+)?\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>');
16
+
17
+ // 行内代码
18
+ html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
19
+
20
+ // 标题
21
+ html = html.replace(/^### (.*$)/gm, '<h3>$1</h3>');
22
+ html = html.replace(/^## (.*$)/gm, '<h2>$1</h2>');
23
+ html = html.replace(/^# (.*$)/gm, '<h1>$1</h1>');
24
+
25
+ // 粗体
26
+ html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
27
+
28
+ // 斜体
29
+ html = html.replace(/\*(.*?)\*/g, '<em>$1</em>');
30
+
31
+ // 链接
32
+ html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>');
33
+
34
+ // 列表
35
+ html = html.replace(/^- (.*$)/gm, '<li>$1</li>');
36
+ html = html.replace(/(<li>.*<\/li>)/s, '<ul>$1</ul>');
37
+
38
+ // 段落
39
+ html = html.replace(/^(?!<[a-z]).*$/gm, '<p>$&</p>');
40
+ html = html.replace(/<p><(h[1-6]|pre|ul|ol|blockquote|table)/g, '<$1');
41
+ html = html.replace(/<\/(h[1-6]|pre|ul|ol|blockquote|table)><\/p>/g, '</$1>');
42
+
43
+ return html;
44
+ }
45
+
46
+ // 检测是否包含 Mermaid 图表
47
+ function hasMermaid(content: string): boolean {
48
+ return /```mermaid/.test(content);
49
+ }
50
+
51
+ // 检测是否包含 Latex 公式
52
+ function hasLatex(content: string): boolean {
53
+ return /\$.*?\$|\\\(.*?\\\)|\\\[.*?\\\]/.test(content);
54
+ }
55
+
56
+ @customElement('ai-markdown')
57
+ export class AiMarkdown extends LitElement {
58
+ static styles = css`
59
+ :host {
60
+ display: block;
61
+ }
62
+
63
+ .markdown-content {
64
+ line-height: 1.6;
65
+ }
66
+
67
+ .markdown-content h1 {
68
+ font-size: 2em;
69
+ margin: 0.67em 0;
70
+ font-weight: 600;
71
+ }
72
+
73
+ .markdown-content h2 {
74
+ font-size: 1.5em;
75
+ margin: 0.83em 0;
76
+ font-weight: 600;
77
+ }
78
+
79
+ .markdown-content h3 {
80
+ font-size: 1.17em;
81
+ margin: 1em 0;
82
+ font-weight: 600;
83
+ }
84
+
85
+ .markdown-content p {
86
+ margin: 0.5em 0;
87
+ }
88
+
89
+ .markdown-content code {
90
+ background-color: var(--ai-bg-secondary, #f5f5f5);
91
+ padding: 2px 6px;
92
+ border-radius: 4px;
93
+ font-family: 'Courier New', monospace;
94
+ font-size: 0.9em;
95
+ }
96
+
97
+ .markdown-content pre {
98
+ background-color: var(--ai-bg-secondary, #f5f5f5);
99
+ padding: 12px;
100
+ border-radius: var(--ai-border-radius, 8px);
101
+ overflow-x: auto;
102
+ margin: 0.5em 0;
103
+ }
104
+
105
+ .markdown-content pre code {
106
+ background-color: transparent;
107
+ padding: 0;
108
+ }
109
+
110
+ .markdown-content blockquote {
111
+ border-left: 4px solid var(--ai-border, #e8e8e8);
112
+ padding-left: 12px;
113
+ margin: 0.5em 0;
114
+ color: var(--ai-text-secondary, #666666);
115
+ }
116
+
117
+ .markdown-content ul,
118
+ .markdown-content ol {
119
+ padding-left: 2em;
120
+ margin: 0.5em 0;
121
+ }
122
+
123
+ .markdown-content a {
124
+ color: var(--ai-primary, #1677ff);
125
+ text-decoration: none;
126
+ }
127
+
128
+ .markdown-content a:hover {
129
+ text-decoration: underline;
130
+ }
131
+
132
+ .markdown-content table {
133
+ border-collapse: collapse;
134
+ width: 100%;
135
+ margin: 0.5em 0;
136
+ }
137
+
138
+ .markdown-content th,
139
+ .markdown-content td {
140
+ border: 1px solid var(--ai-border, #e8e8e8);
141
+ padding: 8px 12px;
142
+ text-align: left;
143
+ }
144
+
145
+ .markdown-content th {
146
+ background-color: var(--ai-bg-secondary, #f5f5f5);
147
+ font-weight: 600;
148
+ }
149
+
150
+ .mermaid-container {
151
+ margin: 1em 0;
152
+ padding: 12px;
153
+ background-color: var(--ai-bg, #ffffff);
154
+ border: 1px solid var(--ai-border, #e8e8e8);
155
+ border-radius: var(--ai-border-radius, 8px);
156
+ overflow-x: auto;
157
+ text-align: center;
158
+ }
159
+
160
+ .latex-formula {
161
+ font-style: italic;
162
+ padding: 0 4px;
163
+ }
164
+
165
+ .latex-block {
166
+ display: block;
167
+ text-align: center;
168
+ margin: 1em 0;
169
+ font-size: 1.2em;
170
+ }
171
+ `;
172
+
173
+ @property({ type: String })
174
+ content = '';
175
+
176
+ @property({ type: Array })
177
+ plugins: string[] = [];
178
+
179
+ render() {
180
+ const hasMermaidContent = hasMermaid(this.content);
181
+ const hasLatexContent = hasLatex(this.content);
182
+
183
+ return html`
184
+ <div class="markdown-content">
185
+ ${hasMermaidContent && this.plugins.includes('mermaid')
186
+ ? html`<div class="mermaid-container">Mermaid 图表(需要集成 Mermaid.js)</div>`
187
+ : ''}
188
+ ${hasLatexContent && this.plugins.includes('latex')
189
+ ? html`<div class="latex-block">Latex 公式(需要集成 KaTeX 或 MathJax)</div>`
190
+ : ''}
191
+ <div>${this.renderMarkdown()}</div>
192
+ </div>
193
+ `;
194
+ }
195
+
196
+ private renderMarkdown() {
197
+ const htmlContent = parseMarkdown(this.content);
198
+ return html`<div .innerHTML=${this.sanitizeHtml(htmlContent)}></div>`;
199
+ }
200
+
201
+ private sanitizeHtml(html: string): string {
202
+ // 简单的 HTML 清理,防止 XSS
203
+ // 在生产环境中应使用 DOMPurify 等库
204
+ const temp = document.createElement('div');
205
+ temp.innerHTML = html;
206
+
207
+ // 移除 script 标签
208
+ const scripts = temp.querySelectorAll('script');
209
+ scripts.forEach(script => script.remove());
210
+
211
+ // 移除危险的 on* 属性
212
+ const allElements = temp.querySelectorAll('*');
213
+ allElements.forEach(el => {
214
+ Array.from(el.attributes).forEach(attr => {
215
+ if (attr.name.startsWith('on')) {
216
+ el.removeAttribute(attr.name);
217
+ }
218
+ });
219
+ });
220
+
221
+ return temp.innerHTML;
222
+ }
223
+ }
224
+
225
+ declare global {
226
+ interface HTMLElementTagNameMap {
227
+ 'ai-markdown': AiMarkdown;
228
+ }
229
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ *
5
+ * 兜底样式 —— 实际视觉由主题接管
6
+ */
7
+
8
+ ai-message {
9
+ display: block;
10
+ }
11
+
12
+ ai-message .ai-message {
13
+ display: flex;
14
+ gap: 8px;
15
+ max-width: 80%;
16
+ }
17
+
18
+ ai-message .ai-message--user {
19
+ flex-direction: row-reverse;
20
+ margin-left: auto;
21
+ }
22
+
23
+ ai-message .ai-message--assistant {
24
+ margin-right: auto;
25
+ }
26
+
27
+ ai-message .ai-message__avatar {
28
+ width: 32px;
29
+ height: 32px;
30
+ border-radius: 50%;
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+ font-size: 13px;
35
+ flex-shrink: 0;
36
+ }
37
+
38
+ ai-message .ai-message__content {
39
+ padding: 10px 14px;
40
+ border-radius: 8px;
41
+ line-height: 1.5;
42
+ word-break: break-word;
43
+ }
44
+
45
+ ai-message .ai-message__time {
46
+ font-size: 11px;
47
+ opacity: 0.55;
48
+ margin-top: 4px;
49
+ }
50
+
51
+ ai-message .ai-message__tool-calls {
52
+ margin-top: 8px;
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: 8px;
56
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+
6
+ import { LitElement, html } from 'lit';
7
+ import { customElement, property } from 'lit/decorators.js';
8
+ import './message.css';
9
+
10
+ // 导入共享类型
11
+ import { Message } from '../types.js';
12
+
13
+ @customElement('ai-message')
14
+ export class AiMessage extends LitElement {
15
+ @property({ type: Boolean })
16
+ headless = true;
17
+
18
+ @property({ type: Object })
19
+ message?: Message;
20
+
21
+ @property({ type: String })
22
+ theme = 'default';
23
+
24
+ // 默认 light DOM,让外部主题 CSS 能命中
25
+ createRenderRoot() {
26
+ if (this.headless) {
27
+ return this;
28
+ }
29
+ return super.createRenderRoot();
30
+ }
31
+
32
+ render() {
33
+ if (!this.message) {
34
+ return html``;
35
+ }
36
+
37
+ const isUser = this.message.role === 'user';
38
+ const roleModifier = isUser ? 'ai-message--user' : 'ai-message--assistant';
39
+ const avatarText = isUser ? '我' : 'AI';
40
+ const time = new Date(this.message.timestamp).toLocaleTimeString('zh-CN', {
41
+ hour: '2-digit',
42
+ minute: '2-digit',
43
+ });
44
+
45
+ return html`
46
+ <div class="ai-message ${roleModifier}">
47
+ <div class="ai-message__avatar">${avatarText}</div>
48
+ <div class="ai-message__body">
49
+ <div class="ai-message__content">${this.message.content}</div>
50
+ ${this.message.toolCalls && this.message.toolCalls.length > 0
51
+ ? html`
52
+ <div class="ai-message__tool-calls">
53
+ ${this.message.toolCalls.map(
54
+ (toolCall) => html`
55
+ <ai-tool-call .toolCall=${toolCall}></ai-tool-call>
56
+ `
57
+ )}
58
+ </div>
59
+ `
60
+ : ''}
61
+ <div class="ai-message__time">${time}</div>
62
+ </div>
63
+ </div>
64
+ `;
65
+ }
66
+ }
67
+
68
+ declare global {
69
+ interface HTMLElementTagNameMap {
70
+ 'ai-message': AiMessage;
71
+ }
72
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @generated-by AI: edenxpzhang
3
+ * @generated-date 2026-05-13
4
+ */
5
+ :host {
6
+ /* 颜色 */
7
+ --ai-primary: #1677ff;
8
+ --ai-bg: #ffffff;
9
+ --ai-bg-secondary: #f5f5f5;
10
+ --ai-text: #333333;
11
+ --ai-text-secondary: #666666;
12
+ --ai-border: #e8e8e8;
13
+ --ai-user-msg-bg: #1677ff;
14
+ --ai-user-msg-text: #ffffff;
15
+ --ai-ai-msg-bg: #f5f5f5;
16
+ --ai-ai-msg-text: #333333;
17
+
18
+ /* 尺寸 */
19
+ --ai-border-radius: 8px;
20
+ --ai-spacing: 12px;
21
+
22
+ /* 字体 */
23
+ --ai-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
24
+ --ai-font-size: 14px;
25
+ }
26
+
27
+ /* 全局样式 */
28
+ .ai-chat-container {
29
+ font-family: var(--ai-font-family);
30
+ font-size: var(--ai-font-size);
31
+ color: var(--ai-text);
32
+ background-color: var(--ai-bg);
33
+ }
34
+
35
+ .ai-message-user {
36
+ background-color: var(--ai-user-msg-bg);
37
+ color: var(--ai-user-msg-text);
38
+ }
39
+
40
+ .ai-message-ai {
41
+ background-color: var(--ai-ai-msg-bg);
42
+ color: var(--ai-ai-msg-text);
43
+ }