@linktr.ee/messaging-react 1.22.0-rc-1771903841 → 1.22.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.
- package/dist/assets/index.css +1 -1
- package/dist/index.js +791 -826
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CustomMessage/CustomMessage.stories.tsx +1 -36
- package/src/components/CustomMessage/MessageTag.stories.tsx +4 -52
- package/src/components/CustomMessage/MessageTag.tsx +8 -51
- package/src/components/CustomMessage/index.tsx +4 -24
- package/src/styles.css +4 -42
- package/src/components/CustomMessage/MessageTag.test.tsx +0 -110
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ const createMockChannel = async (
|
|
|
38
38
|
created_at: new Date(Date.now() - 1000 * 60 * (messages.length - index)),
|
|
39
39
|
updated_at: new Date(Date.now() - 1000 * 60 * (messages.length - index)),
|
|
40
40
|
html: `<p>${msg.text}</p>`,
|
|
41
|
-
attachments:
|
|
41
|
+
attachments: [],
|
|
42
42
|
latest_reactions: [],
|
|
43
43
|
own_reactions: [],
|
|
44
44
|
reaction_counts: {},
|
|
@@ -91,7 +91,6 @@ interface TemplateProps {
|
|
|
91
91
|
text: string
|
|
92
92
|
user: typeof mockUser | { id: string; name: string }
|
|
93
93
|
type?: 'regular' | 'system'
|
|
94
|
-
attachments?: Array<Record<string, unknown>>
|
|
95
94
|
metadata?: {
|
|
96
95
|
custom_type?: 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT'
|
|
97
96
|
amount_text?: string
|
|
@@ -207,37 +206,3 @@ MixedTags.args = {
|
|
|
207
206
|
{ id: 'msg-9', text: 'Thanks for letting me know.', user: mockUser },
|
|
208
207
|
],
|
|
209
208
|
}
|
|
210
|
-
|
|
211
|
-
export const ChatbotVariants: StoryFn<TemplateProps> = Template.bind({})
|
|
212
|
-
ChatbotVariants.args = {
|
|
213
|
-
messages: [
|
|
214
|
-
{
|
|
215
|
-
id: 'msg-1',
|
|
216
|
-
text: 'Would you like to share some details that I can relay to Rupi Kaur?',
|
|
217
|
-
user: participant,
|
|
218
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
id: 'msg-2',
|
|
222
|
-
text: 'I’m sorry to hear that. Are you referring to the course you’ve recently purchased?',
|
|
223
|
-
user: mockUser,
|
|
224
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
id: 'msg-3',
|
|
228
|
-
text: '',
|
|
229
|
-
user: mockUser,
|
|
230
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
231
|
-
attachments: [
|
|
232
|
-
{
|
|
233
|
-
type: 'card',
|
|
234
|
-
title: 'The Perfect Yoga Course',
|
|
235
|
-
title_link: 'https://linktr.ee/rupikaur/learntoyoga',
|
|
236
|
-
text: 'linktr.ee/rupikaur/learntoyoga',
|
|
237
|
-
image_url:
|
|
238
|
-
'https://images.unsplash.com/photo-1571019613914-85f342c1d4b5?auto=format&fit=crop&w=1024&q=80',
|
|
239
|
-
},
|
|
240
|
-
],
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
}
|
|
@@ -64,34 +64,11 @@ Paid.args = {
|
|
|
64
64
|
}),
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export const
|
|
68
|
-
|
|
67
|
+
export const Chatbot: StoryFn<ComponentProps> = Template.bind({})
|
|
68
|
+
Chatbot.args = {
|
|
69
69
|
message: createMockMessage({ metadata: { custom_type: 'MESSAGE_CHATBOT' } }),
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
export const ChatbotSenderText: StoryFn<ComponentProps> = (args) => {
|
|
73
|
-
return (
|
|
74
|
-
<div className="p-12">
|
|
75
|
-
<div className="bg-[#121110] rounded-3xl px-4 py-3 w-[280px]">
|
|
76
|
-
<MessageTag {...args} />
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
ChatbotSenderText.args = {
|
|
82
|
-
message: createMockMessage({ metadata: { custom_type: 'MESSAGE_CHATBOT' } }),
|
|
83
|
-
isMyMessage: true,
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export const ChatbotSenderAttachment: StoryFn<ComponentProps> = Template.bind(
|
|
87
|
-
{}
|
|
88
|
-
)
|
|
89
|
-
ChatbotSenderAttachment.args = {
|
|
90
|
-
message: createMockMessage({ metadata: { custom_type: 'MESSAGE_CHATBOT' } }),
|
|
91
|
-
isMyMessage: true,
|
|
92
|
-
hasAttachment: true,
|
|
93
|
-
}
|
|
94
|
-
|
|
95
72
|
export const NoTag: StoryFn<ComponentProps> = Template.bind({})
|
|
96
73
|
NoTag.args = {
|
|
97
74
|
message: createMockMessage(),
|
|
@@ -127,36 +104,11 @@ export const AllVariants: StoryFn = () => {
|
|
|
127
104
|
/>
|
|
128
105
|
</div>
|
|
129
106
|
<div className="flex items-center gap-4">
|
|
130
|
-
<span className="text-sm w-32">Chatbot
|
|
107
|
+
<span className="text-sm w-32">Chatbot:</span>
|
|
131
108
|
<MessageTag
|
|
132
|
-
message={createMockMessage({
|
|
133
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
134
|
-
})}
|
|
109
|
+
message={createMockMessage({ metadata: { custom_type: 'MESSAGE_CHATBOT' } })}
|
|
135
110
|
/>
|
|
136
111
|
</div>
|
|
137
|
-
<div className="flex items-center gap-4">
|
|
138
|
-
<span className="text-sm w-32">Chatbot (sender):</span>
|
|
139
|
-
<div className="bg-[#121110] rounded-3xl px-4 py-3 w-[280px]">
|
|
140
|
-
<MessageTag
|
|
141
|
-
message={createMockMessage({
|
|
142
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
143
|
-
})}
|
|
144
|
-
isMyMessage
|
|
145
|
-
/>
|
|
146
|
-
</div>
|
|
147
|
-
</div>
|
|
148
|
-
<div className="flex items-center gap-4">
|
|
149
|
-
<span className="text-sm w-32">Chatbot (attachment):</span>
|
|
150
|
-
<div className="w-[280px]">
|
|
151
|
-
<MessageTag
|
|
152
|
-
message={createMockMessage({
|
|
153
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
154
|
-
})}
|
|
155
|
-
isMyMessage
|
|
156
|
-
hasAttachment
|
|
157
|
-
/>
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
112
|
<div className="flex items-center gap-4">
|
|
161
113
|
<span className="text-sm w-32">No tag:</span>
|
|
162
114
|
<MessageTag message={createMockMessage()} />
|
|
@@ -5,20 +5,10 @@ interface MessageTagProps {
|
|
|
5
5
|
message: LocalMessage
|
|
6
6
|
/** When true, renders as a standalone bubble instead of a small tag */
|
|
7
7
|
standalone?: boolean
|
|
8
|
-
/** When true, renders sender-side chatbot variants */
|
|
9
|
-
isMyMessage?: boolean
|
|
10
|
-
/** Whether the message includes an attachment */
|
|
11
|
-
hasAttachment?: boolean
|
|
12
8
|
}
|
|
13
9
|
|
|
14
|
-
const SparkleIcon = (
|
|
15
|
-
<svg
|
|
16
|
-
width={size}
|
|
17
|
-
height={size}
|
|
18
|
-
viewBox="0 0 10 10"
|
|
19
|
-
fill="none"
|
|
20
|
-
aria-hidden="true"
|
|
21
|
-
>
|
|
10
|
+
const SparkleIcon = () => (
|
|
11
|
+
<svg width="12" height="12" viewBox="0 0 10 10" fill="none">
|
|
22
12
|
<path
|
|
23
13
|
d="M10.003 5a.705.705 0 0 1-.469.67L6.7 6.7 5.67 9.535a.715.715 0 0 1-1.34 0L3.3 6.7.466 5.67a.715.715 0 0 1 0-1.34L3.3 3.3 4.33.466a.715.715 0 0 1 1.34 0L6.7 3.3l2.834 1.03a.705.705 0 0 1 .469.67"
|
|
24
14
|
fill="currentColor"
|
|
@@ -54,8 +44,6 @@ export const isTipOnlyMessage = (message: LocalMessage): boolean => {
|
|
|
54
44
|
export const MessageTag = ({
|
|
55
45
|
message,
|
|
56
46
|
standalone = false,
|
|
57
|
-
isMyMessage = false,
|
|
58
|
-
hasAttachment = false,
|
|
59
47
|
}: MessageTagProps) => {
|
|
60
48
|
const isTipOrPaid = isTipOrPaidMessage(message)
|
|
61
49
|
const isChatbot = isChatbotMessage(message)
|
|
@@ -84,44 +72,13 @@ export const MessageTag = ({
|
|
|
84
72
|
)
|
|
85
73
|
}
|
|
86
74
|
|
|
87
|
-
|
|
88
|
-
const chatbotLabel = isSenderAttachmentVariant
|
|
89
|
-
? 'Sent with AI'
|
|
90
|
-
: 'Sent with DM Agent'
|
|
91
|
-
|
|
92
|
-
const chatbotClassName = [
|
|
93
|
-
'message-chatbot-indicator',
|
|
94
|
-
isMyMessage
|
|
95
|
-
? 'message-chatbot-indicator--sender'
|
|
96
|
-
: 'message-chatbot-indicator--receiver',
|
|
97
|
-
isSenderAttachmentVariant
|
|
98
|
-
? 'message-chatbot-indicator--attachment'
|
|
99
|
-
: 'message-chatbot-indicator--text',
|
|
100
|
-
].join(' ')
|
|
101
|
-
|
|
102
|
-
const label = (
|
|
103
|
-
<span className="message-chatbot-indicator__label">{chatbotLabel}</span>
|
|
104
|
-
)
|
|
105
|
-
const icon = (
|
|
106
|
-
<span className="message-chatbot-indicator__icon">
|
|
107
|
-
<SparkleIcon size={isSenderAttachmentVariant ? 12 : 15} />
|
|
108
|
-
</span>
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
// Chatbot indicator variant
|
|
75
|
+
// Chatbot tag
|
|
112
76
|
return (
|
|
113
|
-
<div className=
|
|
114
|
-
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
</>
|
|
119
|
-
) : (
|
|
120
|
-
<>
|
|
121
|
-
{icon}
|
|
122
|
-
{label}
|
|
123
|
-
</>
|
|
124
|
-
)}
|
|
77
|
+
<div className="message-tag message-tag--chatbot">
|
|
78
|
+
<span className="message-tag__icon" style={{ marginTop: -1 }}>
|
|
79
|
+
<SparkleIcon />
|
|
80
|
+
</span>
|
|
81
|
+
<span className="message-tag__label">Chatbot</span>
|
|
125
82
|
</div>
|
|
126
83
|
)
|
|
127
84
|
}
|
|
@@ -117,12 +117,11 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
117
117
|
handleClick = () => setIsBounceDialogOpen(true)
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
const isMine = isMyMessage()
|
|
121
120
|
const rootClassName = classNames(
|
|
122
121
|
'str-chat__message str-chat__message-simple',
|
|
123
122
|
`str-chat__message--${message.type}`,
|
|
124
123
|
`str-chat__message--${message.status}`,
|
|
125
|
-
|
|
124
|
+
isMyMessage()
|
|
126
125
|
? 'str-chat__message--me str-chat__message-simple--me'
|
|
127
126
|
: 'str-chat__message--other',
|
|
128
127
|
message.text ? 'str-chat__message--has-text' : 'has-no-text',
|
|
@@ -143,12 +142,6 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
143
142
|
|
|
144
143
|
const poll = message.poll_id && client.polls.fromState(message.poll_id)
|
|
145
144
|
const isTipOnly = isTipOnlyMessage(message)
|
|
146
|
-
const isChatbot = isChatbotMessage(message)
|
|
147
|
-
const hasRenderableAttachments = !!(
|
|
148
|
-
finalAttachments?.length && !message.quoted_message
|
|
149
|
-
)
|
|
150
|
-
const useAttachmentFooterChatbotTag =
|
|
151
|
-
isChatbot && isMine && hasRenderableAttachments
|
|
152
145
|
|
|
153
146
|
return (
|
|
154
147
|
<>
|
|
@@ -198,13 +191,6 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
198
191
|
) : (
|
|
199
192
|
<div className="str-chat__message-bubble-wrapper">
|
|
200
193
|
<div className="str-chat__message-bubble">
|
|
201
|
-
{isChatbot && !useAttachmentFooterChatbotTag && (
|
|
202
|
-
<MessageTag
|
|
203
|
-
message={message}
|
|
204
|
-
hasAttachment={hasRenderableAttachments}
|
|
205
|
-
isMyMessage={isMine}
|
|
206
|
-
/>
|
|
207
|
-
)}
|
|
208
194
|
{poll && <Poll poll={poll} />}
|
|
209
195
|
{finalAttachments?.length && !message.quoted_message ? (
|
|
210
196
|
<Attachment
|
|
@@ -222,15 +208,9 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
222
208
|
)}
|
|
223
209
|
<MessageErrorIcon />
|
|
224
210
|
</div>
|
|
225
|
-
{/*
|
|
226
|
-
{
|
|
227
|
-
|
|
228
|
-
message={message}
|
|
229
|
-
hasAttachment={hasRenderableAttachments}
|
|
230
|
-
isMyMessage={isMine}
|
|
231
|
-
/>
|
|
232
|
-
)}
|
|
233
|
-
{chatbotVotingEnabled && isChatbot && (
|
|
211
|
+
{/* Tag positioned outside and below the bubble */}
|
|
212
|
+
<MessageTag message={message} />
|
|
213
|
+
{chatbotVotingEnabled && isChatbotMessage(message) && (
|
|
234
214
|
<MessageVoteButtons
|
|
235
215
|
selected={voteState}
|
|
236
216
|
onVoteUp={voteUp}
|
package/src/styles.css
CHANGED
|
@@ -134,45 +134,9 @@
|
|
|
134
134
|
color: #016630;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
.message-chatbot
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
font-size: 10px;
|
|
141
|
-
font-weight: 400;
|
|
142
|
-
line-height: 16px;
|
|
143
|
-
letter-spacing: 0.2px;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.message-chatbot-indicator--text {
|
|
147
|
-
width: 100%;
|
|
148
|
-
gap: 6px;
|
|
149
|
-
margin-bottom: 8px;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.message-chatbot-indicator--receiver {
|
|
153
|
-
justify-content: flex-start;
|
|
154
|
-
color: rgba(0, 0, 0, 0.3);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.message-chatbot-indicator--sender {
|
|
158
|
-
justify-content: flex-end;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.message-chatbot-indicator--sender.message-chatbot-indicator--text {
|
|
162
|
-
color: rgba(255, 255, 255, 0.55);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.message-chatbot-indicator--attachment {
|
|
166
|
-
width: 100%;
|
|
167
|
-
gap: 8px;
|
|
168
|
-
margin-top: 4px;
|
|
169
|
-
color: rgba(0, 0, 0, 0.3);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.message-chatbot-indicator__icon {
|
|
173
|
-
display: inline-flex;
|
|
174
|
-
align-items: center;
|
|
175
|
-
line-height: 1;
|
|
137
|
+
.message-tag--chatbot {
|
|
138
|
+
background-color: transparent;
|
|
139
|
+
color: #7f22fe;
|
|
176
140
|
}
|
|
177
141
|
|
|
178
142
|
/* Message vote buttons (chatbot feedback) */
|
|
@@ -195,9 +159,7 @@
|
|
|
195
159
|
background-color: transparent;
|
|
196
160
|
color: rgba(0, 0, 0, 0.35);
|
|
197
161
|
cursor: pointer;
|
|
198
|
-
transition:
|
|
199
|
-
background-color 0.15s,
|
|
200
|
-
color 0.15s;
|
|
162
|
+
transition: background-color 0.15s, color 0.15s;
|
|
201
163
|
}
|
|
202
164
|
|
|
203
165
|
.message-vote-button:hover {
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { LocalMessage } from 'stream-chat'
|
|
2
|
-
import { describe, expect, it } from 'vitest'
|
|
3
|
-
|
|
4
|
-
import { renderWithProviders, screen } from '../../test/utils'
|
|
5
|
-
|
|
6
|
-
import { MessageTag } from './MessageTag'
|
|
7
|
-
|
|
8
|
-
interface MockMessageOptions {
|
|
9
|
-
metadata?: {
|
|
10
|
-
custom_type?: 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT'
|
|
11
|
-
amount_text?: string
|
|
12
|
-
}
|
|
13
|
-
text?: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const createMockMessage = (options?: MockMessageOptions): LocalMessage =>
|
|
17
|
-
({
|
|
18
|
-
id: 'msg-1',
|
|
19
|
-
text: options?.text ?? 'Hello world',
|
|
20
|
-
type: 'regular',
|
|
21
|
-
created_at: new Date(),
|
|
22
|
-
updated_at: new Date(),
|
|
23
|
-
metadata: options?.metadata,
|
|
24
|
-
}) as LocalMessage
|
|
25
|
-
|
|
26
|
-
describe('MessageTag', () => {
|
|
27
|
-
it('renders receiver chatbot text variant with DM Agent copy and icon first', () => {
|
|
28
|
-
renderWithProviders(
|
|
29
|
-
<MessageTag
|
|
30
|
-
message={createMockMessage({
|
|
31
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
32
|
-
})}
|
|
33
|
-
/>
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
const indicator = screen.getByTestId('message-chatbot-indicator')
|
|
37
|
-
expect(indicator).toHaveTextContent('Sent with DM Agent')
|
|
38
|
-
expect(indicator).toHaveClass('message-chatbot-indicator--receiver')
|
|
39
|
-
expect(indicator).toHaveClass('message-chatbot-indicator--text')
|
|
40
|
-
|
|
41
|
-
expect(indicator.children[0]).toHaveClass('message-chatbot-indicator__icon')
|
|
42
|
-
expect(indicator.children[1]).toHaveClass(
|
|
43
|
-
'message-chatbot-indicator__label'
|
|
44
|
-
)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('renders sender chatbot text variant with mirrored order', () => {
|
|
48
|
-
renderWithProviders(
|
|
49
|
-
<MessageTag
|
|
50
|
-
message={createMockMessage({
|
|
51
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
52
|
-
})}
|
|
53
|
-
isMyMessage
|
|
54
|
-
/>
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
const indicator = screen.getByTestId('message-chatbot-indicator')
|
|
58
|
-
expect(indicator).toHaveTextContent('Sent with DM Agent')
|
|
59
|
-
expect(indicator).toHaveClass('message-chatbot-indicator--sender')
|
|
60
|
-
expect(indicator).toHaveClass('message-chatbot-indicator--text')
|
|
61
|
-
|
|
62
|
-
expect(indicator.children[0]).toHaveClass(
|
|
63
|
-
'message-chatbot-indicator__label'
|
|
64
|
-
)
|
|
65
|
-
expect(indicator.children[1]).toHaveClass('message-chatbot-indicator__icon')
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('renders sender attachment chatbot variant outside-footer copy', () => {
|
|
69
|
-
renderWithProviders(
|
|
70
|
-
<MessageTag
|
|
71
|
-
message={createMockMessage({
|
|
72
|
-
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
73
|
-
})}
|
|
74
|
-
hasAttachment
|
|
75
|
-
isMyMessage
|
|
76
|
-
/>
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
const indicator = screen.getByTestId('message-chatbot-indicator')
|
|
80
|
-
expect(indicator).toHaveTextContent('Sent with AI')
|
|
81
|
-
expect(indicator).toHaveClass('message-chatbot-indicator--sender')
|
|
82
|
-
expect(indicator).toHaveClass('message-chatbot-indicator--attachment')
|
|
83
|
-
|
|
84
|
-
expect(indicator.children[0]).toHaveClass('message-chatbot-indicator__icon')
|
|
85
|
-
expect(indicator.children[1]).toHaveClass(
|
|
86
|
-
'message-chatbot-indicator__label'
|
|
87
|
-
)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
it('keeps tip tag behavior unchanged', () => {
|
|
91
|
-
renderWithProviders(
|
|
92
|
-
<MessageTag
|
|
93
|
-
message={createMockMessage({
|
|
94
|
-
metadata: { custom_type: 'MESSAGE_TIP', amount_text: '$5.50' },
|
|
95
|
-
})}
|
|
96
|
-
/>
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
const tipTag = screen.getByText('Delivered with $5.50 tip')
|
|
100
|
-
expect(tipTag.closest('.message-tag--tip')).not.toBeNull()
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('returns null for non-custom messages', () => {
|
|
104
|
-
const { container } = renderWithProviders(
|
|
105
|
-
<MessageTag message={createMockMessage()} />
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
expect(container.firstChild).toBeNull()
|
|
109
|
-
})
|
|
110
|
-
})
|