@anker-in/campaign-ui 0.0.33-alpha3 → 0.0.33-alpha5
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/dist/cjs/components/chat/Response.d.ts +1 -1
- package/dist/cjs/components/chat/action.d.ts +6 -2
- package/dist/cjs/components/chat/action.js +1 -1
- package/dist/cjs/components/chat/action.js.map +3 -3
- package/dist/cjs/components/chat/button.d.ts +1 -1
- package/dist/cjs/components/chat/button.js +1 -1
- package/dist/cjs/components/chat/button.js.map +3 -3
- package/dist/cjs/components/chat/index.d.ts +24 -8
- package/dist/cjs/components/chat/index.js +1 -1
- package/dist/cjs/components/chat/index.js.map +3 -3
- package/dist/cjs/components/chat/messages.js +1 -1
- package/dist/cjs/components/chat/messages.js.map +3 -3
- package/dist/cjs/components/chat/props.d.ts +1 -2
- package/dist/cjs/components/chat/props.js +1 -1
- package/dist/cjs/components/chat/props.js.map +1 -1
- package/dist/cjs/components/chat/response.js +1 -1
- package/dist/cjs/components/chat/response.js.map +2 -2
- package/dist/cjs/stories/chat.stories.js +1 -1
- package/dist/cjs/stories/chat.stories.js.map +2 -2
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/components/chat/Response.d.ts +1 -1
- package/dist/esm/components/chat/action.d.ts +6 -2
- package/dist/esm/components/chat/action.js +1 -1
- package/dist/esm/components/chat/action.js.map +3 -3
- package/dist/esm/components/chat/button.d.ts +1 -1
- package/dist/esm/components/chat/button.js +1 -1
- package/dist/esm/components/chat/button.js.map +3 -3
- package/dist/esm/components/chat/index.d.ts +24 -8
- package/dist/esm/components/chat/index.js +1 -1
- package/dist/esm/components/chat/index.js.map +3 -3
- package/dist/esm/components/chat/messages.js +1 -1
- package/dist/esm/components/chat/messages.js.map +3 -3
- package/dist/esm/components/chat/props.d.ts +1 -2
- package/dist/esm/components/chat/props.js.map +1 -1
- package/dist/esm/components/chat/response.js +1 -1
- package/dist/esm/components/chat/response.js.map +2 -2
- package/dist/esm/stories/chat.stories.js +1 -1
- package/dist/esm/stories/chat.stories.js.map +2 -2
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/components/chat/action.tsx +46 -11
- package/src/components/chat/button.tsx +2 -9
- package/src/components/chat/index.tsx +61 -38
- package/src/components/chat/messages.tsx +43 -2
- package/src/components/chat/props.ts +1 -2
- package/src/components/chat/response.tsx +6 -4
- package/src/stories/chat.stories.tsx +6 -7
- package/src/styles/css/messages.css +8 -0
- package/src/styles/css/response.css +0 -1
|
@@ -14,31 +14,38 @@ interface Message {
|
|
|
14
14
|
export interface ActionProps {
|
|
15
15
|
start?: string
|
|
16
16
|
history: Message[]
|
|
17
|
+
addtocartHandler?: (_args: any) => Promise<any>
|
|
18
|
+
gotocheckoutRender?: string | ((_props: any) => React.ReactElement)
|
|
19
|
+
gotocartRender?: string | ((_props: any) => React.ReactElement)
|
|
17
20
|
addtocartRender?: string | ((_props: any) => React.ReactElement)
|
|
18
|
-
productRender?: string | ((_props: any) => React.ReactElement)
|
|
19
21
|
signupRender?: string | ((_props: any) => React.ReactElement)
|
|
22
|
+
productRender?: string | ((_props: any) => React.ReactElement)
|
|
23
|
+
productRenderTipMessage?: string
|
|
20
24
|
children?: React.ReactNode
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
export const CopilotAction = ({
|
|
24
28
|
start,
|
|
25
29
|
history,
|
|
30
|
+
addtocartHandler,
|
|
31
|
+
gotocheckoutRender,
|
|
32
|
+
gotocartRender,
|
|
26
33
|
addtocartRender,
|
|
27
34
|
productRender,
|
|
28
35
|
signupRender,
|
|
29
36
|
children,
|
|
30
37
|
}: ActionProps) => {
|
|
31
|
-
const { setMessages } = useCopilotChat()
|
|
38
|
+
const { setMessages, appendMessage, isLoading } = useCopilotChat()
|
|
32
39
|
|
|
33
40
|
useEffect(() => {
|
|
34
41
|
const originhistory = history?.filter(value => value?.content || value?.arguments)
|
|
35
42
|
if (originhistory?.length > 0) {
|
|
36
43
|
const content = originhistory?.map(value => {
|
|
37
44
|
if (value?.name && value?.arguments) {
|
|
38
|
-
|
|
45
|
+
const args = value?.arguments?.map((item: any) => (item ? { ...item, ishistory: true } : {}))
|
|
39
46
|
return new ActionExecutionMessage({
|
|
40
47
|
name: value?.name,
|
|
41
|
-
arguments:
|
|
48
|
+
arguments: args,
|
|
42
49
|
scope: value?.scope,
|
|
43
50
|
})
|
|
44
51
|
}
|
|
@@ -52,25 +59,53 @@ export const CopilotAction = ({
|
|
|
52
59
|
}, [history])
|
|
53
60
|
|
|
54
61
|
useCopilotAction({
|
|
55
|
-
name: '
|
|
56
|
-
description: '
|
|
62
|
+
name: 'go_to_checkout',
|
|
63
|
+
description: 'go to cart',
|
|
57
64
|
parameters: [{ sku: '', handle: '' }] as any,
|
|
58
|
-
render:
|
|
65
|
+
render: gotocheckoutRender || (props => <div className="hidden">{JSON.stringify(props)}</div>),
|
|
59
66
|
handler: function () {
|
|
60
67
|
// console.log('buynow-props', props)
|
|
61
68
|
},
|
|
62
69
|
})
|
|
63
70
|
|
|
64
71
|
useCopilotAction({
|
|
65
|
-
name: '
|
|
66
|
-
description: '
|
|
72
|
+
name: 'go_to_cart',
|
|
73
|
+
description: 'go to cart',
|
|
67
74
|
parameters: [{ sku: '', handle: '' }] as any,
|
|
68
|
-
render:
|
|
75
|
+
render: gotocartRender || (props => <div className="hidden">{JSON.stringify(props)}</div>),
|
|
69
76
|
handler: function () {
|
|
70
77
|
// console.log('buynow-props', props)
|
|
71
78
|
},
|
|
72
79
|
})
|
|
73
80
|
|
|
81
|
+
useCopilotAction({
|
|
82
|
+
name: 'add_to_cart',
|
|
83
|
+
description: 'add to cart',
|
|
84
|
+
parameters: [{ sku: '', handle: '' }] as any,
|
|
85
|
+
render: addtocartRender || (props => <div className="hidden">{JSON.stringify(props)}</div>),
|
|
86
|
+
handler: function (props) {
|
|
87
|
+
addtocartHandler && addtocartHandler(props)
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
useCopilotAction({
|
|
92
|
+
name: 'show_product_card',
|
|
93
|
+
description: 'product card',
|
|
94
|
+
parameters: [{ sku: '', handle: '' }] as any,
|
|
95
|
+
render: productRender || (props => <div className="hidden">{JSON.stringify(props)}</div>),
|
|
96
|
+
handler: function (props) {
|
|
97
|
+
console.log('show_product_card-props', props)
|
|
98
|
+
// const ishistory = props?.find((item: { ishistory: any }) => item?.ishistory)
|
|
99
|
+
// if (!ishistory) {
|
|
100
|
+
// const content = new TextMessage({
|
|
101
|
+
// content: 'show product card',
|
|
102
|
+
// role: Role.Assistant,
|
|
103
|
+
// })
|
|
104
|
+
// appendMessage(content)
|
|
105
|
+
// }
|
|
106
|
+
},
|
|
107
|
+
})
|
|
108
|
+
|
|
74
109
|
useCopilotAction({
|
|
75
110
|
name: 'signup',
|
|
76
111
|
description: 'signup',
|
|
@@ -79,7 +114,7 @@ export const CopilotAction = ({
|
|
|
79
114
|
name: 'signup',
|
|
80
115
|
},
|
|
81
116
|
] as any,
|
|
82
|
-
render: signupRender || (props => <div>{JSON.stringify(props)}</div>),
|
|
117
|
+
render: signupRender || (props => <div className="hidden">{JSON.stringify(props)}</div>),
|
|
83
118
|
handler: function () {
|
|
84
119
|
// console.log('signup-props', props)
|
|
85
120
|
},
|
|
@@ -2,18 +2,11 @@ import { useChatContext } from '@copilotkit/react-ui'
|
|
|
2
2
|
|
|
3
3
|
import type { ButtonProps } from './props.js'
|
|
4
4
|
|
|
5
|
-
const DefaultButton = ({ setOpen
|
|
5
|
+
const DefaultButton = ({ setOpen }: ButtonProps) => {
|
|
6
6
|
const context = useChatContext()
|
|
7
7
|
|
|
8
8
|
return (
|
|
9
|
-
<button
|
|
10
|
-
onClick={() => {
|
|
11
|
-
setOpen(true)
|
|
12
|
-
setOpenTip(false)
|
|
13
|
-
}}
|
|
14
|
-
className="copilotKitButton "
|
|
15
|
-
aria-label="Open Chat"
|
|
16
|
-
>
|
|
9
|
+
<button onClick={() => setOpen()} className="copilotKitButton " aria-label="Open Chat">
|
|
17
10
|
<div className="copilotKitButtonIcon copilotKitButtonIconOpen">{context.icons.openIcon}</div>
|
|
18
11
|
<div className="copilotKitButtonIcon copilotKitButtonIconClose">{context.icons.closeIcon}</div>
|
|
19
12
|
</button>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
-
import React from 'react'
|
|
2
|
+
import React, { useMemo } from 'react'
|
|
3
3
|
import { useCallback, useState, useEffect } from 'react'
|
|
4
4
|
import { CopilotKit } from '@copilotkit/react-core'
|
|
5
5
|
import { CopilotPopup } from '@copilotkit/react-ui'
|
|
@@ -13,37 +13,53 @@ import fetcher from '../../helpers/fetcher.js'
|
|
|
13
13
|
export interface ChatProps {
|
|
14
14
|
title: string
|
|
15
15
|
runtimeUrl: string
|
|
16
|
-
|
|
16
|
+
shopifyDomain: string
|
|
17
17
|
/** GA 的 client id
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
userId: string
|
|
20
20
|
/** 是否登陆用户 0 or 1
|
|
21
21
|
*/
|
|
22
22
|
account?: string
|
|
23
23
|
/** 用户浏览器语言
|
|
24
24
|
*/
|
|
25
25
|
locale?: string
|
|
26
|
+
/** 开场白
|
|
27
|
+
*/
|
|
28
|
+
prologue?: string
|
|
26
29
|
/** ?a=1&b=2
|
|
27
30
|
*/
|
|
28
31
|
query?: string
|
|
29
32
|
/** 'follow' or 'unfollow' | true or false
|
|
33
|
+
* follow: ResponseButton 会跟随在 messages 的后边
|
|
34
|
+
* unfollow: ResponseButton 在聊天框底部
|
|
30
35
|
*/
|
|
31
36
|
showResponseButton?: string | boolean
|
|
32
|
-
/**
|
|
37
|
+
/** 跳转 checkout action 卡片,接受参数: {"status":"complete","args":[{"sku":["A3936031"],"handle":"space-a40-a3936031"}],"result":""}
|
|
33
38
|
* 后端接口文档:https://anker-in.feishu.cn/wiki/DOYJwE9oxipWmYk072ncnJNznBb
|
|
34
39
|
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
40
|
+
gotocheckoutRender?: string | ((_props: any) => React.ReactElement)
|
|
41
|
+
/** 打开购物车 action 卡片,接受参数: {"status":"complete","args":[{"sku":["A3936031"],"handle":"space-a40-a3936031"}],"result":""}
|
|
37
42
|
* 后端接口文档:https://anker-in.feishu.cn/wiki/DOYJwE9oxipWmYk072ncnJNznBb
|
|
38
43
|
*/
|
|
39
|
-
|
|
40
|
-
/**
|
|
44
|
+
gotocartRender?: string | ((_props: any) => React.ReactElement)
|
|
45
|
+
/** 打开购物车 action 的触发事件
|
|
46
|
+
*/
|
|
47
|
+
addtocartHandler?: (_args: any) => Promise<any>
|
|
48
|
+
/** 加购卡片,接受参数: {"status":"complete","args":[{"sku":["A3936031"],"handle":"space-a40-a3936031"}],"result":""}
|
|
49
|
+
* 后端接口文档:https://anker-in.feishu.cn/wiki/DOYJwE9oxipWmYk072ncnJNznBb
|
|
50
|
+
*/
|
|
51
|
+
addtocartRender?: string | ((_props: any) => React.ReactElement)
|
|
52
|
+
/** 订阅卡片,接受参数: {"status":"complete","args":[{"sku":["A3936031"],"handle":"space-a40-a3936031"}],"result":""}
|
|
41
53
|
* 后端接口文档:https://anker-in.feishu.cn/wiki/DOYJwE9oxipWmYk072ncnJNznBb
|
|
42
54
|
*/
|
|
43
55
|
signupRender?: string | ((_props: any) => React.ReactElement)
|
|
56
|
+
/** 产品卡片,接受参数: {"status":"complete","args":[{"sku":["A3936031"],"handle":"space-a40-a3936031"}],"result":""}
|
|
57
|
+
* 后端接口文档:https://anker-in.feishu.cn/wiki/DOYJwE9oxipWmYk072ncnJNznBb
|
|
58
|
+
*/
|
|
59
|
+
productRender?: string | ((_props: any) => React.ReactElement)
|
|
44
60
|
/** CopilotPopup 自定义参数,参考:https://docs.copilotkit.ai/reference/components/CopilotPopup */
|
|
45
61
|
popup?: any
|
|
46
|
-
/** 文案,{"popupTip": "Hi ! Welcome to soundcore Innovations live chat!", "popupTipTimeout": [3000, 6000]} */
|
|
62
|
+
/** 文案,{"productRenderTipMessage": "","popupTip": "Hi ! Welcome to soundcore Innovations live chat!", "popupTipTimeout": [3000, 6000]} */
|
|
47
63
|
lang?: any
|
|
48
64
|
/** 参考此文档:https://docs.copilotkit.ai/concepts/customize-look-and-feel */
|
|
49
65
|
style?: any
|
|
@@ -55,12 +71,15 @@ const Chat = (props: ChatProps) => {
|
|
|
55
71
|
title,
|
|
56
72
|
runtimeUrl,
|
|
57
73
|
popup,
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
shopifyDomain,
|
|
75
|
+
userId = '',
|
|
60
76
|
account = '',
|
|
77
|
+
prologue = '',
|
|
61
78
|
locale = '',
|
|
62
79
|
query = '',
|
|
63
80
|
showResponseButton,
|
|
81
|
+
gotocheckoutRender,
|
|
82
|
+
gotocartRender,
|
|
64
83
|
addtocartRender,
|
|
65
84
|
productRender,
|
|
66
85
|
signupRender,
|
|
@@ -72,33 +91,43 @@ const Chat = (props: ChatProps) => {
|
|
|
72
91
|
|
|
73
92
|
const [openTip, setOpenTip] = useState(false)
|
|
74
93
|
const [openPopup, setOpenPopup] = useState(false)
|
|
75
|
-
const [start, setstart] = useState(
|
|
94
|
+
const [start, setstart] = useState(prologue)
|
|
76
95
|
const [currentSuggestions, setCurrentSuggestions] = useState([])
|
|
77
96
|
const [history, sethistory] = useState<[{ content: string; role: string }] | []>([])
|
|
78
97
|
|
|
98
|
+
const headers = useMemo(
|
|
99
|
+
() => ({
|
|
100
|
+
'x-user-id': userId || '',
|
|
101
|
+
'x-shopify-domain': shopifyDomain,
|
|
102
|
+
'x-member-ship': account,
|
|
103
|
+
'x-user-locale': locale,
|
|
104
|
+
}),
|
|
105
|
+
[userId, shopifyDomain, account, locale]
|
|
106
|
+
)
|
|
107
|
+
|
|
79
108
|
const getStart = useCallback(async () => {
|
|
80
109
|
const result = await fetcher({
|
|
81
110
|
url: `${runtimeUrl}/copilotkit/start${query}`,
|
|
82
111
|
method: 'GET',
|
|
83
|
-
headers
|
|
112
|
+
headers,
|
|
84
113
|
})
|
|
85
114
|
|
|
86
115
|
setCurrentSuggestions(result?.suggested_questions?.map((item: string) => ({ message: item, title: item })) || [])
|
|
87
116
|
setstart(result?.opening_statement || '')
|
|
88
117
|
sethistory(result?.history || [])
|
|
89
|
-
}, [
|
|
118
|
+
}, [userId, shopifyDomain, account, locale])
|
|
90
119
|
|
|
91
120
|
const getSuggestions = useCallback(async () => {
|
|
92
121
|
const result = await fetcher({
|
|
93
122
|
url: `${runtimeUrl}/copilotkit/suggested_questions${query}`,
|
|
94
123
|
method: 'GET',
|
|
95
|
-
headers
|
|
124
|
+
headers,
|
|
96
125
|
})
|
|
97
126
|
|
|
98
127
|
setCurrentSuggestions(
|
|
99
128
|
result?.suggested_questions?.data?.map((item: string) => ({ message: item, title: item })) || []
|
|
100
129
|
)
|
|
101
|
-
}, [
|
|
130
|
+
}, [userId, shopifyDomain, account, locale])
|
|
102
131
|
|
|
103
132
|
const setOpenTipFn = () => {
|
|
104
133
|
if (!openTip) setOpenTip(true)
|
|
@@ -117,20 +146,10 @@ const Chat = (props: ChatProps) => {
|
|
|
117
146
|
}
|
|
118
147
|
}, [])
|
|
119
148
|
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
if (!start) {
|
|
122
|
-
getStart()
|
|
123
|
-
}
|
|
124
|
-
}, [])
|
|
125
|
-
|
|
126
149
|
return (
|
|
127
150
|
<div className={className} style={style || {}}>
|
|
128
|
-
{
|
|
129
|
-
<CopilotKit
|
|
130
|
-
runtimeUrl={`${runtimeUrl}/copilotkit/chat${query}`}
|
|
131
|
-
showDevConsole={false}
|
|
132
|
-
headers={{ user_id: user_id || '', shopify_domain: shopify_domain, account, locale }}
|
|
133
|
-
>
|
|
151
|
+
{userId && runtimeUrl && (
|
|
152
|
+
<CopilotKit runtimeUrl={`${runtimeUrl}/copilotkit/chat${query}`} showDevConsole={false} headers={headers}>
|
|
134
153
|
<CopilotPopup
|
|
135
154
|
{...popup}
|
|
136
155
|
showResponseButton={showResponseButton !== 'follow'}
|
|
@@ -152,29 +171,30 @@ const Chat = (props: ChatProps) => {
|
|
|
152
171
|
<Suggestions currentSuggestions={currentSuggestions} />
|
|
153
172
|
</Messages>
|
|
154
173
|
)}
|
|
155
|
-
Button={({ open, setOpen }) => {
|
|
174
|
+
Button={({ open, setOpen: setOpenDefault }) => {
|
|
156
175
|
const Button = popup?.Button || DefaultButton
|
|
157
176
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
158
177
|
useEffect(() => {
|
|
159
178
|
setOpenPopup(open)
|
|
160
179
|
}, [open])
|
|
180
|
+
|
|
181
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
182
|
+
const setOpen = useCallback(() => {
|
|
183
|
+
setOpenDefault(!open)
|
|
184
|
+
setOpenTip(false)
|
|
185
|
+
if (!start || !history?.length) getStart()
|
|
186
|
+
}, [start])
|
|
187
|
+
|
|
161
188
|
return (
|
|
162
189
|
<>
|
|
163
190
|
{lang?.popupTip && openTip && !openPopup && (
|
|
164
191
|
<div className="copilotKitPopup copilotKitPopupTip">
|
|
165
|
-
<button
|
|
166
|
-
onClick={() => {
|
|
167
|
-
setOpen(true)
|
|
168
|
-
setOpenTip(false)
|
|
169
|
-
}}
|
|
170
|
-
aria-label="Open Chat"
|
|
171
|
-
className="copilotKitPopupTipContent"
|
|
172
|
-
>
|
|
192
|
+
<button onClick={setOpen} aria-label="Open Chat" className="copilotKitPopupTipContent">
|
|
173
193
|
{lang?.popupTip}
|
|
174
194
|
</button>
|
|
175
195
|
</div>
|
|
176
196
|
)}
|
|
177
|
-
<Button open={open} setOpen={setOpen}
|
|
197
|
+
<Button open={open} setOpen={setOpen} />
|
|
178
198
|
</>
|
|
179
199
|
)
|
|
180
200
|
}}
|
|
@@ -182,9 +202,12 @@ const Chat = (props: ChatProps) => {
|
|
|
182
202
|
<CopilotAction
|
|
183
203
|
start={start}
|
|
184
204
|
history={history}
|
|
205
|
+
gotocartRender={gotocartRender}
|
|
206
|
+
gotocheckoutRender={gotocheckoutRender}
|
|
185
207
|
addtocartRender={addtocartRender}
|
|
186
208
|
productRender={productRender}
|
|
187
209
|
signupRender={signupRender}
|
|
210
|
+
productRenderTipMessage={lang?.productRenderTipMessage}
|
|
188
211
|
/>
|
|
189
212
|
</CopilotPopup>
|
|
190
213
|
</CopilotKit>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo } from 'react'
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react'
|
|
2
2
|
import type { MessagesProps } from './props.js'
|
|
3
3
|
import { useChatContext } from '@copilotkit/react-ui'
|
|
4
4
|
import { Markdown } from './markdown.js'
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
} from '@copilotkit/runtime-client-gql'
|
|
14
14
|
|
|
15
15
|
const Messages = ({ messages, inProgress, ResponseButton, children }: MessagesProps) => {
|
|
16
|
+
const [isExpanded, setIsExpanded] = useState(true)
|
|
17
|
+
|
|
16
18
|
const { chatComponentsCache } = useCopilotContext()
|
|
17
19
|
|
|
18
20
|
const context = useChatContext()
|
|
@@ -35,6 +37,7 @@ const Messages = ({ messages, inProgress, ResponseButton, children }: MessagesPr
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const messagesEndRef = React.useRef<HTMLDivElement>(null)
|
|
40
|
+
const messagesEndChildRef = React.useRef<HTMLDivElement>(null)
|
|
38
41
|
|
|
39
42
|
const scrollToBottom = () => {
|
|
40
43
|
if (messagesEndRef.current) {
|
|
@@ -48,6 +51,40 @@ const Messages = ({ messages, inProgress, ResponseButton, children }: MessagesPr
|
|
|
48
51
|
scrollToBottom()
|
|
49
52
|
}, [messages])
|
|
50
53
|
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const textarea = document.querySelector('.copilotKitInput textarea') as HTMLTextAreaElement
|
|
56
|
+
|
|
57
|
+
textarea &&
|
|
58
|
+
textarea.addEventListener('click', function () {
|
|
59
|
+
if (textarea.value && document.activeElement === textarea) {
|
|
60
|
+
setIsExpanded(false)
|
|
61
|
+
} else {
|
|
62
|
+
setIsExpanded(true)
|
|
63
|
+
scrollToBottom()
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
textarea &&
|
|
67
|
+
textarea.addEventListener('input', function () {
|
|
68
|
+
if (textarea.value && document.activeElement === textarea) {
|
|
69
|
+
setIsExpanded(false)
|
|
70
|
+
} else {
|
|
71
|
+
setIsExpanded(true)
|
|
72
|
+
scrollToBottom()
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
}, [])
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
const content = messagesEndChildRef.current
|
|
79
|
+
if (isExpanded && content) {
|
|
80
|
+
content.style.maxHeight = '500px'
|
|
81
|
+
content.style.overflow = 'visible'
|
|
82
|
+
} else if (!isExpanded && content) {
|
|
83
|
+
content.style.maxHeight = '0'
|
|
84
|
+
content.style.overflow = 'hidden'
|
|
85
|
+
}
|
|
86
|
+
}, [isExpanded])
|
|
87
|
+
|
|
51
88
|
return (
|
|
52
89
|
<div className="copilotKitMessages">
|
|
53
90
|
{messages.map((message, index) => {
|
|
@@ -140,7 +177,11 @@ const Messages = ({ messages, inProgress, ResponseButton, children }: MessagesPr
|
|
|
140
177
|
}
|
|
141
178
|
})}
|
|
142
179
|
<div className="responseButtonBox">{ResponseButton}</div>
|
|
143
|
-
<footer ref={messagesEndRef}>
|
|
180
|
+
<footer ref={messagesEndRef}>
|
|
181
|
+
<div className="copilotKitMessagesFooter" ref={messagesEndChildRef}>
|
|
182
|
+
{children}
|
|
183
|
+
</div>
|
|
184
|
+
</footer>
|
|
144
185
|
</div>
|
|
145
186
|
)
|
|
146
187
|
}
|
|
@@ -7,10 +7,12 @@ const ResponseButton = () => {
|
|
|
7
7
|
const { isLoading, reloadMessages, stopGeneration } = useCopilotChat()
|
|
8
8
|
|
|
9
9
|
return (
|
|
10
|
-
|
|
11
|
-
{isLoading ?
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
!isLoading && (
|
|
11
|
+
<button onClick={isLoading ? stopGeneration : reloadMessages} className="copilotKitResponseButton">
|
|
12
|
+
{isLoading ? context.labels.stopGenerating : context.labels.regenerateResponse}
|
|
13
|
+
<span>{isLoading ? context.icons.stopIcon : context.icons.regenerateIcon}</span>
|
|
14
|
+
</button>
|
|
15
|
+
)
|
|
14
16
|
)
|
|
15
17
|
}
|
|
16
18
|
|
|
@@ -12,16 +12,15 @@ const meta: Meta<typeof Chat> = {
|
|
|
12
12
|
component: Chat,
|
|
13
13
|
args: {
|
|
14
14
|
title: 'DTC Live Chat',
|
|
15
|
-
runtimeUrl: 'https://beta-
|
|
16
|
-
|
|
15
|
+
runtimeUrl: 'https://beta-api-livechat.anker.com',
|
|
16
|
+
shopifyDomain: 'soundcoreusa.myshopify.com',
|
|
17
17
|
},
|
|
18
18
|
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
|
19
19
|
tags: ['autodocs'],
|
|
20
20
|
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
|
21
21
|
decorators: [
|
|
22
22
|
Story => (
|
|
23
|
-
<div style={{
|
|
24
|
-
{/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it */}
|
|
23
|
+
<div style={{ height: '700px' }}>
|
|
25
24
|
<Story />
|
|
26
25
|
</div>
|
|
27
26
|
),
|
|
@@ -33,9 +32,9 @@ export default meta
|
|
|
33
32
|
export const Default: Story = {
|
|
34
33
|
args: {
|
|
35
34
|
title: 'DTC Live Chat',
|
|
36
|
-
runtimeUrl: 'https://beta-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
runtimeUrl: 'https://beta-api-livechat.anker.com',
|
|
36
|
+
shopifyDomain: 'soundcoreusa.myshopify.com',
|
|
37
|
+
userId: 'arno7',
|
|
39
38
|
showResponseButton: 'follow',
|
|
40
39
|
lang: { popupTip: 'Hi ! Welcome to soundcore Innovations live chat!', popupTipTimeout: [3000, 6000] },
|
|
41
40
|
},
|
|
@@ -75,3 +75,11 @@
|
|
|
75
75
|
.copilotKitMessage.copilotKitAssistantMessage:has(.copilotKitMarkdown:empty) {
|
|
76
76
|
display: none;
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
.copilotKitMessagesFooter {
|
|
80
|
+
transition: all 300ms ease-out;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.copilotKitCustomAssistantMessage .hidden {
|
|
84
|
+
display: none !important;
|
|
85
|
+
}
|