@anker-in/campaign-ui 0.5.22 → 0.5.24

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 (28) hide show
  1. package/README.md +21 -1
  2. package/dist/cjs/components/credits/creditsWaysToGetCredits/useActions.js +1 -1
  3. package/dist/cjs/components/credits/creditsWaysToGetCredits/useActions.js.map +2 -2
  4. package/dist/cjs/components/credits/modal/SubscribeModal.d.ts +1 -0
  5. package/dist/cjs/components/credits/modal/SubscribeModal.js +1 -1
  6. package/dist/cjs/components/credits/modal/SubscribeModal.js.map +3 -3
  7. package/dist/esm/components/credits/creditsWaysToGetCredits/useActions.js +1 -1
  8. package/dist/esm/components/credits/creditsWaysToGetCredits/useActions.js.map +2 -2
  9. package/dist/esm/components/credits/modal/SubscribeModal.d.ts +1 -0
  10. package/dist/esm/components/credits/modal/SubscribeModal.js +1 -1
  11. package/dist/esm/components/credits/modal/SubscribeModal.js.map +3 -3
  12. package/package.json +1 -1
  13. package/src/components/credits/creditsWaysToGetCredits/useActions.ts +1 -1
  14. package/src/components/credits/modal/SubscribeModal.tsx +75 -63
  15. package/dist/cjs/stories/LiveChatWidget.stories.d.ts +0 -14
  16. package/dist/cjs/stories/LiveChatWidget.stories.js +0 -52
  17. package/dist/cjs/stories/LiveChatWidget.stories.js.map +0 -7
  18. package/dist/cjs/stories/chat.stories.d.ts +0 -7
  19. package/dist/cjs/stories/chat.stories.js +0 -2
  20. package/dist/cjs/stories/chat.stories.js.map +0 -7
  21. package/dist/esm/stories/LiveChatWidget.stories.d.ts +0 -14
  22. package/dist/esm/stories/LiveChatWidget.stories.js +0 -52
  23. package/dist/esm/stories/LiveChatWidget.stories.js.map +0 -7
  24. package/dist/esm/stories/chat.stories.d.ts +0 -7
  25. package/dist/esm/stories/chat.stories.js +0 -2
  26. package/dist/esm/stories/chat.stories.js.map +0 -7
  27. package/src/stories/LiveChatWidget.stories.tsx +0 -317
  28. package/src/stories/chat.stories.tsx +0 -41
@@ -1,317 +0,0 @@
1
- /**
2
- * LiveChatWidget Storybook Stories
3
- * 展示 LiveChat 组件的各种使用场景和配置
4
- */
5
-
6
- import type { Meta, StoryObj } from '@storybook/react'
7
- import { LiveChatWidget } from '../components/LiveChatWidget'
8
- import type { MessageRenderer, MessageContent } from '../components/LiveChatWidget'
9
- import '../styles/livechat.css'
10
-
11
- const meta: Meta<typeof LiveChatWidget> = {
12
- title: 'Campaign/LiveChatWidget',
13
- component: LiveChatWidget,
14
- parameters: {
15
- layout: 'fullscreen',
16
- docs: {
17
- story: {
18
- inline: false,
19
- iframeHeight: 500,
20
- },
21
- description: {
22
- component: `
23
- # LiveChat 聊天组件
24
-
25
- 可复用的气泡弹窗聊天组件,支持 SSE 流式消息、自定义渲染器和多种消息类型。
26
-
27
- ## 功能特性
28
-
29
- - 🎈 **气泡弹窗**: 可自定义位置的悬浮气泡按钮
30
- - 💬 **流式消息**: 基于 SSE 的实时流式响应
31
- - 📦 **多种消息类型**: 文本、商品卡片、商品列表、政策、快捷回复等
32
- - 🎨 **可定制**: 支持自定义品牌颜色、Logo、渲染器
33
- - 📱 **响应式**: 移动端全屏,桌面端固定尺寸
34
- - 💾 **会话管理**: 自动管理 userId 和 sessionId
35
- - 🔒 **安全防护**: 内置 XSS 防护和输入验证
36
-
37
- ## 基础用法
38
-
39
- \`\`\`tsx
40
- import { LiveChatWidget } from '@anker-in/campaign-ui'
41
- import '@anker-in/campaign-ui/livechat.css'
42
-
43
- function App() {
44
- return (
45
- <LiveChatWidget
46
- apiBaseUrl="https://beta-api-livechat.anker.com"
47
- site="www.eufy.com"
48
- channel_code="web_homepage"
49
- welcomeMessage="你好!我是 AI 助手"
50
- />
51
- )
52
- }
53
- \`\`\`
54
-
55
- ## 自定义渲染器
56
-
57
- \`\`\`tsx
58
- const customRenderers = {
59
- video: {
60
- render: (content) => (
61
- <video src={content.url} controls className="w-full rounded" />
62
- )
63
- }
64
- }
65
-
66
- <LiveChatWidget
67
- apiBaseUrl="..."
68
- site="..."
69
- customRenderers={customRenderers}
70
- />
71
- \`\`\`
72
- `,
73
- },
74
- },
75
- },
76
- tags: ['autodocs'],
77
- argTypes: {
78
- apiBaseUrl: {
79
- control: 'text',
80
- description: 'API 基础 URL',
81
- },
82
- headers: {
83
- control: 'object',
84
- description: '自定义请求头,将在所有 API 请求中添加',
85
- table: {
86
- defaultValue: { summary: 'undefined' },
87
- },
88
- },
89
- recaptchaSitekey: {
90
- control: 'text',
91
- description: 'Google reCAPTCHA v3 site key,提供此参数将自动启用 reCAPTCHA v3 验证',
92
- table: {
93
- defaultValue: { summary: 'undefined' },
94
- },
95
- },
96
- recaptchaAction: {
97
- control: 'text',
98
- description: 'reCAPTCHA action 名称,用于区分不同的验证场景',
99
- table: {
100
- defaultValue: { summary: '"activity"' },
101
- },
102
- },
103
- site: {
104
- control: 'text',
105
- description: 'Shopify 店铺 URL',
106
- },
107
- channelCode: {
108
- control: 'text',
109
- description: '渠道编码,用于标识来源渠道',
110
- table: {
111
- defaultValue: { summary: 'undefined' },
112
- },
113
- },
114
- welcomeMessage: {
115
- control: 'text',
116
- description: '欢迎消息',
117
- table: {
118
- defaultValue: { summary: '你好!我是 AI 助手,有什么可以帮助你的吗?' },
119
- },
120
- },
121
- logoUrl: {
122
- control: 'text',
123
- description: 'Logo URL',
124
- },
125
- position: {
126
- control: 'object',
127
- description: '气泡按钮位置对象',
128
- table: {
129
- defaultValue: { summary: '{ bottom: "1.5rem", right: "1.5rem" }' },
130
- },
131
- },
132
- },
133
- args: {
134
- apiBaseUrl: 'http://172.16.38.183:3003',
135
- site: 'www.eufy.com',
136
- loginUserId: 'test_test',
137
- welcomeMessage: '你好!我是 AI 助手,有什么可以帮助你的吗?',
138
- },
139
- }
140
-
141
- export default meta
142
- type Story = StoryObj<typeof LiveChatWidget>
143
-
144
- /**
145
- * 默认配置 - 展示所有功能
146
- */
147
- export const Default: Story = {
148
- args: {
149
- // 基础配置
150
- loginUserId: 'test_test1',
151
- apiBaseUrl: 'https://beta-api-v2-livechat.anker.com',
152
- site: 'beta.soundcore.com',
153
- channelCode: 'dtc',
154
- title: 'eufy AI Assistant',
155
- cartId: 'gid://shopify/Cart/hWNAAJweS9IkeRKib4LRy9PY?key=ff1f9b24e74b3f11f5574539e7cbbb2f',
156
- accessToken: '47b1aa2c0797043f9baba39388029d70',
157
-
158
- // 自定义位置
159
- position: { bottom: '24px', right: '30px' },
160
-
161
- // 欢迎消息
162
- welcomeMessage: '',
163
-
164
- // 快捷回复
165
- quickReplies: [
166
- { id: '1', label: 'Product Info', value: 'Tell me about your products', icon: '📦' },
167
- { id: '2', label: 'Track Order', value: 'I want to track my order', icon: '🚚' },
168
- { id: '3', label: 'Support', value: 'I need help with my device', icon: '🔧' },
169
- { id: '4', label: 'Recommendations', value: 'Recommend products for me', icon: '⭐' },
170
- ],
171
-
172
- // 法规协议弹窗
173
- complianceConfig: {
174
- title: "Hi! I'm your eufy AI assistant.",
175
- content:
176
- 'AI-generated responses can be inaccurate. Please verify important info. Do not input sensitive personal data.',
177
- checkboxText:
178
- 'By starting to use "Live Chat", you agree to Anker\'s <a href="https://www.anker.com/pages/privacy-policy" target="_blank" rel="noopener noreferrer" style="text-decoration: underline;">LIVE CHAT PRIVACY NOTICE</a>.',
179
- agreeButtonText: 'Agree',
180
- },
181
-
182
- // reCAPTCHA 配置(取消注释以启用)
183
- // recaptchaSitekey: '6LfS4J4pAAAAACX1e_WrxutmxxzCK7FU4WzVqL14',
184
- recaptchaAction: 'livechat',
185
-
186
- // 显示新会话按钮
187
- showNewSessionButton: true,
188
-
189
- // 自定义文案
190
- commonText: {
191
- learnMore: 'Learn More',
192
- total: 'Total',
193
- },
194
-
195
- // 自定义消息渲染器
196
- customRenderers: {
197
- video: {
198
- render: (content: MessageContent) => {
199
- const videoContent = content as any
200
- return (
201
- <div className="w-full">
202
- <video src={videoContent.url} controls className="w-full rounded-lg" poster={videoContent.poster}>
203
- Your browser does not support video playback
204
- </video>
205
- {videoContent.title && <p className="mt-2 text-sm text-gray-600">{videoContent.title}</p>}
206
- </div>
207
- )
208
- },
209
- } as MessageRenderer,
210
- image_gallery: {
211
- render: (content: MessageContent) => {
212
- const galleryContent = content as any
213
- const images = galleryContent.images || []
214
- return (
215
- <div className="grid grid-cols-2 gap-2">
216
- {images.map((image: any, index: number) => (
217
- <div key={index} className="relative aspect-square">
218
- <img
219
- src={image.url}
220
- alt={image.alt || `Image ${index + 1}`}
221
- className="size-full rounded-lg object-cover"
222
- />
223
- </div>
224
- ))}
225
- </div>
226
- )
227
- },
228
- } as MessageRenderer,
229
- },
230
-
231
- // 自定义产品卡片渲染
232
- productCardRender: (product, productHandle) => {
233
- // product 可能为 undefined,此时可用 productHandle 查询
234
- if (!product) {
235
- return (
236
- <div style={{ padding: '16px', border: '1px dashed #ccc', borderRadius: '8px', textAlign: 'center' }}>
237
- <p>Product loading... (handle: {productHandle})</p>
238
- </div>
239
- )
240
- }
241
-
242
- const imageUrl = product?.featured_image || ''
243
- const title = product?.title || ''
244
- const description = product?.description || ''
245
- const averageRating = product?.average_rating
246
-
247
- return (
248
- <div
249
- style={{
250
- border: '2px solid #4CAF50',
251
- borderRadius: '16px',
252
- padding: '16px',
253
- margin: '12px 0',
254
- backgroundColor: '#f0f9ff',
255
- boxShadow: '0 4px 12px rgba(76, 175, 80, 0.15)',
256
- }}
257
- >
258
- <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
259
- {imageUrl && (
260
- <img
261
- src={imageUrl}
262
- alt={title}
263
- style={{ width: '60px', height: '60px', borderRadius: '8px', objectFit: 'cover' }}
264
- />
265
- )}
266
- <div style={{ flex: 1 }}>
267
- <h4 style={{ margin: '0 0 4px 0', fontSize: '16px', fontWeight: 'bold' }}>{title}</h4>
268
- {description && (
269
- <p style={{ margin: 0, fontSize: '12px', color: '#666', lineHeight: 1.4 }}>
270
- {description.slice(0, 80)}...
271
- </p>
272
- )}
273
- {averageRating && (
274
- <span style={{ fontSize: '12px', color: '#FFB800' }}>Rating: {averageRating.toFixed(1)}</span>
275
- )}
276
- </div>
277
- <button
278
- style={{
279
- padding: '8px 16px',
280
- backgroundColor: '#4CAF50',
281
- color: 'white',
282
- borderRadius: '8px',
283
- border: 'none',
284
- cursor: 'pointer',
285
- }}
286
- onClick={() => console.log('View product:', productHandle, product)}
287
- >
288
- View
289
- </button>
290
- </div>
291
- </div>
292
- )
293
- },
294
- },
295
-
296
- render: args => (
297
- <LiveChatWidget
298
- {...args}
299
- // 所有事件回调
300
- onOpen={() => console.log('[LiveChat] Chat opened')}
301
- onClose={() => console.log('[LiveChat] Chat closed')}
302
- onMessageSend={(message: string) => console.log('[LiveChat] Message sent:', message)}
303
- onError={(error: Error) => console.error('[LiveChat] Error:', error)}
304
- onTextMessage={() => console.log('[LiveChat] AI text message received')}
305
- onProductList={() => console.log('[LiveChat] Product list received')}
306
- onPromotionList={() => console.log('[LiveChat] Promotion list received')}
307
- onAddToCart={(product: any) => {
308
- console.log('[LiveChat] Add to cart:', product)
309
- alert(`Added "${product.title}" to cart!`)
310
- }}
311
- onCart={(cartId: string, checkoutUrl?: string) => {
312
- console.log('[LiveChat] Cart clicked:', { cartId, checkoutUrl })
313
- alert(`Cart ID: ${cartId}`)
314
- }}
315
- />
316
- ),
317
- }
@@ -1,41 +0,0 @@
1
- import React from 'react'
2
- import type { Meta, StoryObj } from '@storybook/react'
3
- import { Chat } from '../components/index'
4
- import '../styles/chat.css'
5
-
6
- type Story = StoryObj<typeof meta>
7
-
8
- // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
9
- const meta: Meta<typeof Chat> = {
10
- // 同时定义了页面左侧菜单
11
- title: 'Campaign/Chat',
12
- component: Chat,
13
- args: {
14
- title: 'DTC Live Chat',
15
- runtimeUrl: 'https://beta-api-livechat.anker.com',
16
- shopifyDomain: 'soundcoreusa.myshopify.com',
17
- },
18
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
19
- tags: ['autodocs'],
20
- // More on argTypes: https://storybook.js.org/docs/api/argtypes
21
- decorators: [
22
- Story => (
23
- <div style={{ height: '700px' }}>
24
- <Story />
25
- </div>
26
- ),
27
- ],
28
- } satisfies Meta<typeof Chat>
29
-
30
- export default meta
31
-
32
- export const Default: Story = {
33
- args: {
34
- title: 'DTC Live Chat',
35
- runtimeUrl: 'https://beta-api-livechat.anker.com',
36
- shopifyDomain: 'soundcoreusa.myshopify.com',
37
- userId: 'arno7',
38
- showResponseButton: 'follow',
39
- lang: { popupTip: 'Hi ! Welcome to soundcore Innovations live chat!', popupTipTimeout: [3000, 6000] },
40
- },
41
- }