@linktr.ee/messaging-react 1.21.2 → 1.22.0-rc-1771556455

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.21.2",
3
+ "version": "1.22.0-rc-1771556455",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,56 @@
1
+ import type { Meta, StoryFn } from '@storybook/react'
2
+ import type { EventComponentProps } from 'stream-chat-react'
3
+
4
+ import { CustomSystemMessage } from '.'
5
+
6
+ const meta: Meta<typeof CustomSystemMessage> = {
7
+ title: 'CustomSystemMessage',
8
+ component: CustomSystemMessage,
9
+ parameters: {
10
+ layout: 'centered',
11
+ },
12
+ }
13
+ export default meta
14
+
15
+ const createStoryProps = (
16
+ messageOverrides: Partial<EventComponentProps['message']>
17
+ ): EventComponentProps =>
18
+ ({
19
+ message: {
20
+ id: 'system-message-1',
21
+ type: 'system',
22
+ text: 'System message',
23
+ hide_date: true,
24
+ ...messageOverrides,
25
+ },
26
+ }) as EventComponentProps
27
+
28
+ const Template: StoryFn<EventComponentProps> = (args) => (
29
+ <div className="w-[420px] bg-white p-6">
30
+ <CustomSystemMessage {...args} />
31
+ </div>
32
+ )
33
+
34
+ export const DmAgentPaused: StoryFn<EventComponentProps> = Template.bind({})
35
+ DmAgentPaused.args = createStoryProps({
36
+ text: 'DM Agent paused for this conversation',
37
+ metadata: {
38
+ custom_type: 'SYSTEM_DM_AGENT_PAUSED',
39
+ },
40
+ })
41
+
42
+ export const DmAgentResumed: StoryFn<EventComponentProps> = Template.bind({})
43
+ DmAgentResumed.args = createStoryProps({
44
+ text: 'DM Agent resumed for this conversation',
45
+ metadata: {
46
+ custom_type: 'SYSTEM_DM_AGENT_RESUMED',
47
+ },
48
+ })
49
+
50
+ export const GenericFallback: StoryFn<EventComponentProps> = Template.bind({})
51
+ GenericFallback.args = createStoryProps({
52
+ text: 'Message activity event',
53
+ metadata: {
54
+ custom_type: 'MESSAGE_CHATBOT',
55
+ },
56
+ })
@@ -0,0 +1,78 @@
1
+ import type { EventComponentProps } from 'stream-chat-react'
2
+ import { describe, expect, it } from 'vitest'
3
+
4
+ import type { DmAgentSystemType } from '../../stream-custom-data'
5
+ import { renderWithProviders, screen } from '../../test/utils'
6
+
7
+ import { CustomSystemMessage } from '.'
8
+
9
+ const createProps = (
10
+ messageOverrides: Partial<EventComponentProps['message']> = {}
11
+ ): EventComponentProps =>
12
+ ({
13
+ message: {
14
+ id: 'system-message-1',
15
+ type: 'system',
16
+ text: 'System message',
17
+ hide_date: true,
18
+ ...messageOverrides,
19
+ },
20
+ }) as EventComponentProps
21
+
22
+ describe('CustomSystemMessage', () => {
23
+ it('detects DM Agent system subtype from metadata.custom_type', () => {
24
+ renderWithProviders(
25
+ <CustomSystemMessage
26
+ {...createProps({
27
+ text: 'DM Agent paused',
28
+ metadata: {
29
+ custom_type: 'SYSTEM_DM_AGENT_PAUSED',
30
+ },
31
+ dm_agent_system_type: 'SYSTEM_DM_AGENT_RESUMED',
32
+ })}
33
+ />
34
+ )
35
+
36
+ const dmAgentSystemMessage = screen.getByTestId('dm-agent-system-message')
37
+ expect(dmAgentSystemMessage).toHaveClass(
38
+ 'mes-dm-agent-system-message--paused'
39
+ )
40
+ expect(dmAgentSystemMessage).toHaveTextContent('DM Agent paused')
41
+ })
42
+
43
+ it('falls back to message.dm_agent_system_type when metadata subtype is absent', () => {
44
+ renderWithProviders(
45
+ <CustomSystemMessage
46
+ {...createProps({
47
+ text: 'DM Agent resumed',
48
+ metadata: {},
49
+ dm_agent_system_type: 'SYSTEM_DM_AGENT_RESUMED',
50
+ })}
51
+ />
52
+ )
53
+
54
+ const dmAgentSystemMessage = screen.getByTestId('dm-agent-system-message')
55
+ expect(dmAgentSystemMessage).toHaveClass(
56
+ 'mes-dm-agent-system-message--resumed'
57
+ )
58
+ expect(dmAgentSystemMessage).toHaveTextContent('DM Agent resumed')
59
+ })
60
+
61
+ it('falls back to legacy generic rendering when subtype is absent or unknown', () => {
62
+ const { container } = renderWithProviders(
63
+ <CustomSystemMessage
64
+ {...createProps({
65
+ text: 'Legacy system message',
66
+ dm_agent_system_type:
67
+ 'SYSTEM_DM_AGENT_UNKNOWN' as unknown as DmAgentSystemType,
68
+ })}
69
+ />
70
+ )
71
+
72
+ expect(screen.queryByTestId('dm-agent-system-message')).not.toBeInTheDocument()
73
+ expect(screen.getByText('Legacy system message')).toBeInTheDocument()
74
+ expect(
75
+ container.querySelector('.str-chat__message--system__line')
76
+ ).toBeInTheDocument()
77
+ })
78
+ })
@@ -1,7 +1,71 @@
1
+ import { Robot } from '@phosphor-icons/react'
1
2
  import { MessageTimestamp, type EventComponentProps } from 'stream-chat-react'
2
3
 
4
+ import type { DmAgentSystemType } from '../../stream-custom-data'
5
+
6
+ const DM_AGENT_SYSTEM_TYPES: readonly DmAgentSystemType[] = [
7
+ 'SYSTEM_DM_AGENT_PAUSED',
8
+ 'SYSTEM_DM_AGENT_RESUMED',
9
+ ]
10
+
11
+ const DM_AGENT_SYSTEM_MESSAGE_VARIANT_CLASS: Record<DmAgentSystemType, string> =
12
+ {
13
+ SYSTEM_DM_AGENT_PAUSED: 'mes-dm-agent-system-message--paused',
14
+ SYSTEM_DM_AGENT_RESUMED: 'mes-dm-agent-system-message--resumed',
15
+ }
16
+
17
+ const DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT: Record<DmAgentSystemType, string> =
18
+ {
19
+ SYSTEM_DM_AGENT_PAUSED: 'DM Agent paused',
20
+ SYSTEM_DM_AGENT_RESUMED: 'DM Agent resumed',
21
+ }
22
+
23
+ const isDmAgentSystemType = (
24
+ value: string | undefined
25
+ ): value is DmAgentSystemType => {
26
+ return DM_AGENT_SYSTEM_TYPES.includes(value as DmAgentSystemType)
27
+ }
28
+
29
+ const getDmAgentSystemType = (
30
+ message: EventComponentProps['message']
31
+ ): DmAgentSystemType | undefined => {
32
+ const metadataCustomType = message.metadata?.custom_type
33
+ if (isDmAgentSystemType(metadataCustomType)) {
34
+ return metadataCustomType
35
+ }
36
+
37
+ const fallbackType = message.dm_agent_system_type
38
+ if (isDmAgentSystemType(fallbackType)) {
39
+ return fallbackType
40
+ }
41
+
42
+ return undefined
43
+ }
44
+
3
45
  export const CustomSystemMessage: React.FC<EventComponentProps> = (props) => {
4
46
  const isDateHidden = props.message.hide_date === true
47
+ const dmAgentSystemType = getDmAgentSystemType(props.message)
48
+
49
+ if (dmAgentSystemType) {
50
+ const messageText =
51
+ props.message.text?.trim() ||
52
+ DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT[dmAgentSystemType]
53
+
54
+ return (
55
+ <div className="str-chat__message--system" data-testid="message-system">
56
+ <div
57
+ className={`mes-dm-agent-system-message ${
58
+ DM_AGENT_SYSTEM_MESSAGE_VARIANT_CLASS[dmAgentSystemType]
59
+ }`}
60
+ data-testid="dm-agent-system-message"
61
+ >
62
+ <Robot size={14} weight="fill" aria-hidden />
63
+ <p>{messageText}</p>
64
+ </div>
65
+ {!isDateHidden && <MessageTimestamp message={props.message} />}
66
+ </div>
67
+ )
68
+ }
5
69
 
6
70
  return (
7
71
  <div className="str-chat__message--system" data-testid="message-system">
@@ -14,4 +78,3 @@ export const CustomSystemMessage: React.FC<EventComponentProps> = (props) => {
14
78
  </div>
15
79
  )
16
80
  }
17
-
@@ -14,12 +14,22 @@
14
14
 
15
15
  import 'stream-chat'
16
16
 
17
+ export type DmAgentSystemType =
18
+ | 'SYSTEM_DM_AGENT_PAUSED'
19
+ | 'SYSTEM_DM_AGENT_RESUMED'
20
+
21
+ export type MessageCustomType =
22
+ | 'MESSAGE_TIP'
23
+ | 'MESSAGE_PAID'
24
+ | 'MESSAGE_CHATBOT'
25
+ | DmAgentSystemType
26
+
17
27
  /**
18
28
  * Message metadata for paid messaging and chatbot flows.
19
29
  * Used to identify message types and payment status.
20
30
  */
21
31
  export interface MessageMetadata {
22
- custom_type?: 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT'
32
+ custom_type?: MessageCustomType
23
33
  amount_text?: string
24
34
  payment_status?: string
25
35
  payment_intent_id?: string
@@ -38,5 +48,10 @@ declare module 'stream-chat' {
38
48
  * Contains type and payment information.
39
49
  */
40
50
  metadata?: MessageMetadata
51
+ /**
52
+ * DM Agent-specific system message type.
53
+ * Used as a fallback when metadata.custom_type is not available.
54
+ */
55
+ dm_agent_system_type?: DmAgentSystemType
41
56
  }
42
57
  }
package/src/styles.css CHANGED
@@ -187,3 +187,31 @@
187
187
  color: #016e1a;
188
188
  background-color: #dbf0e0;
189
189
  }
190
+
191
+ /* DM Agent pause/resume system message variants */
192
+ .mes-dm-agent-system-message {
193
+ display: inline-flex;
194
+ align-items: center;
195
+ gap: 6px;
196
+ margin-inline: auto;
197
+ margin-bottom: 4px;
198
+ padding: 6px 10px;
199
+ border-radius: 9999px;
200
+ font-size: 12px;
201
+ font-weight: 500;
202
+ line-height: 1;
203
+ }
204
+
205
+ .mes-dm-agent-system-message p {
206
+ margin: 0;
207
+ }
208
+
209
+ .mes-dm-agent-system-message--paused {
210
+ background-color: #fff4d6;
211
+ color: #7a4a00;
212
+ }
213
+
214
+ .mes-dm-agent-system-message--resumed {
215
+ background-color: #dbf0e0;
216
+ color: #016630;
217
+ }