@linktr.ee/messaging-react 3.12.3-rc-1784036508 → 3.12.3-rc-1784083967

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/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-D5GopgL7.cjs");exports.ActionButton=e.ActionButton;exports.Avatar=e.Avatar;exports.ChannelEmptyState=e.ChannelEmptyState;exports.ChannelList=e.ChannelList;exports.ChannelView=e.ChannelView;exports.CustomMessageProvider=e.CustomMessageProvider;exports.FaqList=e.FaqList;exports.FaqListItem=e.FaqListItem;exports.LinkAttachment=e.LinkAttachment;exports.LockedAttachment=e.LockedAttachment;exports.MediaMessage=e.MediaMessage;exports.MessageAttachment=e.MessageAttachment;exports.MessageBubble=e.MessageBubble;exports.MessageVoteButtons=e.MessageVoteButtons;exports.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.buildCompactMetaLabel=e.buildCompactMetaLabel;exports.formatFileSize=e.formatFileSize;exports.formatRelativeTime=e.formatRelativeTime;exports.getFileExtensionLabel=e.getFileExtensionLabel;exports.getMessageDisplayText=e.getMessageDisplayText;exports.isLinkAttachment=e.isLinkAttachment;exports.isUuidLike=e.isUuidLike;exports.messageAttachmentGroupPositionFromStream=e.bubbleGroupPositionFromStream;exports.normalizeLanguageCode=e.normalizeLanguageCode;exports.resolveConversationParticipant=e.resolveConversationParticipant;exports.resolveLinkAttachment=e.resolveLinkAttachment;exports.resolveMediaFromMessage=e.resolveMediaFromMessage;exports.resolveParticipantDisplayName=e.resolveParticipantDisplayName;exports.useComposerLocked=e.useComposerLocked;exports.useCustomMessage=e.useCustomMessage;exports.useMessageVote=e.useMessageVote;exports.useMessaging=e.useMessaging;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DSxpS5J9.cjs");exports.ActionButton=e.ActionButton;exports.Avatar=e.Avatar;exports.ChannelEmptyState=e.ChannelEmptyState;exports.ChannelList=e.ChannelList;exports.ChannelView=e.ChannelView;exports.CustomMessageProvider=e.CustomMessageProvider;exports.FaqList=e.FaqList;exports.FaqListItem=e.FaqListItem;exports.LinkAttachment=e.LinkAttachment;exports.LockedAttachment=e.LockedAttachment;exports.MediaMessage=e.MediaMessage;exports.MessageAttachment=e.MessageAttachment;exports.MessageBubble=e.MessageBubble;exports.MessageVoteButtons=e.MessageVoteButtons;exports.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.buildCompactMetaLabel=e.buildCompactMetaLabel;exports.formatFileSize=e.formatFileSize;exports.formatRelativeTime=e.formatRelativeTime;exports.getFileExtensionLabel=e.getFileExtensionLabel;exports.getMessageDisplayText=e.getMessageDisplayText;exports.isLinkAttachment=e.isLinkAttachment;exports.isUuidLike=e.isUuidLike;exports.messageAttachmentGroupPositionFromStream=e.bubbleGroupPositionFromStream;exports.normalizeLanguageCode=e.normalizeLanguageCode;exports.resolveConversationParticipant=e.resolveConversationParticipant;exports.resolveLinkAttachment=e.resolveLinkAttachment;exports.resolveMediaFromMessage=e.resolveMediaFromMessage;exports.resolveParticipantDisplayName=e.resolveParticipantDisplayName;exports.useComposerLocked=e.useComposerLocked;exports.useCustomMessage=e.useCustomMessage;exports.useMessageVote=e.useMessageVote;exports.useMessaging=e.useMessaging;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -1713,6 +1713,16 @@ declare module 'stream-chat' {
1713
1713
  * Whether DM agent auto-replies are paused for this channel.
1714
1714
  */
1715
1715
  chatbot_paused?: boolean;
1716
+ /**
1717
+ * Customer classification tag for this conversation (e.g. CUSTOMER_PAID).
1718
+ */
1719
+ customer_tag?: string;
1720
+ }
1721
+ interface CustomMemberData {
1722
+ /**
1723
+ * Whether this member follows the channel's linker account.
1724
+ */
1725
+ is_follower?: boolean;
1716
1726
  }
1717
1727
  interface CustomMessageData {
1718
1728
  /**
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, b as t, C as i, c as o, d as n, e as m, F as r, f as g, L as l, h as M, M as u, i as c, j as L, k as h, l as d, m as p, n as v, p as C, q as A, s as k, t as F, u as b, v as P, w as f, x, y, z as B, B as S, D as q, E as z, G as D, H as E, I as V } from "./index-FDgJhTIG.js";
1
+ import { a as e, b as t, C as i, c as o, d as n, e as m, F as r, f as g, L as l, h as M, M as u, i as c, j as L, k as h, l as d, m as p, n as v, p as C, q as A, s as k, t as F, u as b, v as P, w as f, x, y, z as B, B as S, D as q, E as z, G as D, H as E, I as V } from "./index-B2BrYTjw.js";
2
2
  export {
3
3
  e as ActionButton,
4
4
  t as Avatar,
package/dist/testing.d.ts CHANGED
@@ -133,6 +133,16 @@ declare module 'stream-chat' {
133
133
  * Whether DM agent auto-replies are paused for this channel.
134
134
  */
135
135
  chatbot_paused?: boolean;
136
+ /**
137
+ * Customer classification tag for this conversation (e.g. CUSTOMER_PAID).
138
+ */
139
+ customer_tag?: string;
140
+ }
141
+ interface CustomMemberData {
142
+ /**
143
+ * Whether this member follows the channel's linker account.
144
+ */
145
+ is_follower?: boolean;
136
146
  }
137
147
  interface CustomMessageData {
138
148
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "3.12.3-rc-1784036508",
3
+ "version": "3.12.3-rc-1784083967",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@linktr.ee/component-library": "11.8.6",
53
- "@linktr.ee/messaging-core": "2.3.0-rc-1784036508",
53
+ "@linktr.ee/messaging-core": "2.3.0-rc-1784083967",
54
54
  "@phosphor-icons/react": "^2.1.10"
55
55
  },
56
56
  "devDependencies": {
@@ -7,7 +7,7 @@ import {
7
7
  } from '@phosphor-icons/react'
8
8
  import classNames from 'classnames'
9
9
  import React from 'react'
10
- import type { ChannelMemberResponse, Channel as ChannelType } from 'stream-chat'
10
+ import type { Channel as ChannelType } from 'stream-chat'
11
11
  import { useChannelStateContext, useChatContext } from 'stream-chat-react'
12
12
 
13
13
  import { useChannelStar } from '../hooks/useChannelStar'
@@ -30,17 +30,6 @@ const isCustomerPaidTag = (value: unknown) =>
30
30
  .replace(/[\s-]+/g, '_')
31
31
  .toUpperCase() === CUSTOMER_PAID_TAG
32
32
 
33
- const hasCustomerPaidTag = (participant?: ChannelMemberResponse) => {
34
- const member = participant as
35
- | {
36
- customerTag?: unknown
37
- customer_tag?: unknown
38
- }
39
- | undefined
40
-
41
- return [member?.customerTag, member?.customer_tag].some(isCustomerPaidTag)
42
- }
43
-
44
33
  interface ChannelHeaderRedesignProps {
45
34
  className?: string
46
35
  onBack?: () => void
@@ -96,7 +85,9 @@ export const ChannelHeaderRedesign: React.FC<ChannelHeaderRedesignProps> = ({
96
85
  const participantName = resolveParticipantDisplayName(participant?.user)
97
86
  const participantImage = participant?.user?.image
98
87
  const isStarred = useChannelStar(channel)
99
- const isPaidCustomer = hasCustomerPaidTag(participant)
88
+ const isPaidCustomer =
89
+ isCustomerPaidTag(channel.data?.customer_tag) &&
90
+ participant?.is_follower === true
100
91
 
101
92
  const handleStarClick = async () => {
102
93
  try {
@@ -44,7 +44,7 @@ const createMockChannel = async (
44
44
  hasMessages = true,
45
45
  followerStatus?: string | boolean,
46
46
  isFrozen = false,
47
- participantCustomerTag?: string,
47
+ channelCustomerTag?: string,
48
48
  hasScrollableMessages = false
49
49
  ) => {
50
50
  const participant = mockParticipants[0]
@@ -140,6 +140,7 @@ const createMockChannel = async (
140
140
  const channelData: Record<string, unknown> = {
141
141
  members: [mockUser.id, participant.id],
142
142
  frozen: isFrozen,
143
+ ...(channelCustomerTag ? { customer_tag: channelCustomerTag } : {}),
143
144
  }
144
145
 
145
146
  // Add follower status if provided
@@ -178,7 +179,7 @@ const createMockChannel = async (
178
179
  user_id: participant.id,
179
180
  role: 'member',
180
181
  is_account: true,
181
- customerTag: participantCustomerTag,
182
+ ...(channelCustomerTag ? { is_follower: true } : {}),
182
183
  },
183
184
  }
184
185
  return {
@@ -214,7 +215,7 @@ type TemplateProps = ComponentProps & {
214
215
  name?: string
215
216
  image?: string
216
217
  }
217
- participantCustomerTag?: string
218
+ channelCustomerTag?: string
218
219
  hasScrollableMessages?: boolean
219
220
  }
220
221
 
@@ -223,7 +224,7 @@ const Template: StoryFn<TemplateProps> = (args) => {
223
224
  hasMessages = true,
224
225
  followerStatus,
225
226
  isFrozen = false,
226
- participantCustomerTag,
227
+ channelCustomerTag,
227
228
  hasScrollableMessages,
228
229
  typingUser,
229
230
  ...channelViewProps
@@ -238,7 +239,7 @@ const Template: StoryFn<TemplateProps> = (args) => {
238
239
  hasMessages,
239
240
  followerStatus,
240
241
  isFrozen,
241
- participantCustomerTag,
242
+ channelCustomerTag,
242
243
  hasScrollableMessages
243
244
  ).then((mockChannel) => {
244
245
  setChannel(mockChannel)
@@ -248,7 +249,7 @@ const Template: StoryFn<TemplateProps> = (args) => {
248
249
  hasMessages,
249
250
  followerStatus,
250
251
  isFrozen,
251
- participantCustomerTag,
252
+ channelCustomerTag,
252
253
  hasScrollableMessages,
253
254
  ])
254
255
 
@@ -305,7 +306,7 @@ export const ParticipantIdentityTrigger: StoryFn<TemplateProps> = Template.bind(
305
306
  ParticipantIdentityTrigger.args = {
306
307
  showBackButton: false,
307
308
  showStarButton: true,
308
- participantCustomerTag: 'CUSTOMER_PAID',
309
+ channelCustomerTag: 'CUSTOMER_PAID',
309
310
  hasScrollableMessages: true,
310
311
  onParticipantNameClick: () =>
311
312
  // eslint-disable-next-line no-alert
@@ -8,6 +8,7 @@ import { ChannelView } from './ChannelView'
8
8
 
9
9
  let activeChannel: unknown
10
10
  let activeChannelProps: Record<string, unknown> = {}
11
+ let activeComponentOverrides: Record<string, unknown> = {}
11
12
 
12
13
  vi.mock('stream-chat-react', () => ({
13
14
  Channel: (props: {
@@ -25,9 +26,16 @@ vi.mock('stream-chat-react', () => ({
25
26
  MessageList: ({ head }: { head?: React.ReactElement }) => (
26
27
  <div data-testid="message-list">{head}</div>
27
28
  ),
28
- WithComponents: ({ children }: { children: React.ReactNode }) => (
29
- <>{children}</>
30
- ),
29
+ WithComponents: ({
30
+ children,
31
+ overrides,
32
+ }: {
33
+ children: React.ReactNode
34
+ overrides?: Record<string, unknown>
35
+ }) => {
36
+ activeComponentOverrides = overrides ?? {}
37
+ return <>{children}</>
38
+ },
31
39
  useMessageContext: () => ({ message: { id: 'message-1', text: 'hello' } }),
32
40
  useChannelStateContext: () => ({ channel: activeChannel }),
33
41
  useChatContext: () => ({
@@ -103,12 +111,14 @@ const createChannel = ({
103
111
  username: undefined as string | undefined,
104
112
  is_account: true,
105
113
  },
106
- otherMemberCustomerTag,
114
+ channelCustomerTag,
115
+ otherMemberIsFollower,
107
116
  }: {
108
117
  currentUserId?: 'visitor-1' | 'linker-1'
109
118
  currentUserRole?: 'owner' | 'member'
110
119
  messages?: Channel['state']['messages']
111
- otherMemberCustomerTag?: string
120
+ channelCustomerTag?: string
121
+ otherMemberIsFollower?: boolean
112
122
  otherUser?: {
113
123
  id: string
114
124
  name?: string
@@ -119,7 +129,9 @@ const createChannel = ({
119
129
  ({
120
130
  id: 'channel-1',
121
131
  cid: 'messaging:channel-1',
122
- data: {},
132
+ data: {
133
+ customer_tag: channelCustomerTag,
134
+ },
123
135
  _client: { userID: currentUserId },
124
136
  state: {
125
137
  members: {
@@ -139,7 +151,7 @@ const createChannel = ({
139
151
  (currentUserId === 'visitor-1' ? 'linker-1' : 'visitor-1'),
140
152
  is_account: otherUser.is_account ?? currentUserId === 'visitor-1',
141
153
  },
142
- customerTag: otherMemberCustomerTag,
154
+ is_follower: otherMemberIsFollower,
143
155
  role: currentUserRole === 'owner' ? 'member' : 'owner',
144
156
  },
145
157
  },
@@ -158,6 +170,7 @@ describe('ChannelView', () => {
158
170
  beforeEach(() => {
159
171
  activeChannel = undefined
160
172
  activeChannelProps = {}
173
+ activeComponentOverrides = {}
161
174
  avatarRenderCalls.length = 0
162
175
  channelActionsMenuProps.length = 0
163
176
  messageInputProps.length = 0
@@ -242,7 +255,8 @@ describe('ChannelView', () => {
242
255
  renderWithProviders(
243
256
  <ChannelView
244
257
  channel={createChannel({
245
- otherMemberCustomerTag: 'CUSTOMER_PAID',
258
+ channelCustomerTag: 'CUSTOMER_PAID',
259
+ otherMemberIsFollower: true,
246
260
  })}
247
261
  onParticipantNameClick={vi.fn()}
248
262
  showStarButton={true}
@@ -253,6 +267,20 @@ describe('ChannelView', () => {
253
267
  expect(screen.getByLabelText('Starred conversation')).toBeInTheDocument()
254
268
  })
255
269
 
270
+ it('hides the paid customer badge when the participant is not a follower', () => {
271
+ renderWithProviders(
272
+ <ChannelView
273
+ channel={createChannel({
274
+ channelCustomerTag: 'CUSTOMER_PAID',
275
+ otherMemberIsFollower: false,
276
+ })}
277
+ onParticipantNameClick={vi.fn()}
278
+ />
279
+ )
280
+
281
+ expect(screen.queryByLabelText('Paid customer')).not.toBeInTheDocument()
282
+ })
283
+
256
284
  it('renders the redesigned header outside MessageList head when all messages are deleted', () => {
257
285
  renderWithProviders(
258
286
  <ChannelView
@@ -282,6 +310,17 @@ describe('ChannelView', () => {
282
310
  ).toBeGreaterThan(0)
283
311
  })
284
312
 
313
+ it('suppresses stream unread message UI overrides', () => {
314
+ renderWithProviders(<ChannelView channel={createChannel()} />)
315
+
316
+ expect(activeComponentOverrides.UnreadMessagesSeparator).toBeTypeOf(
317
+ 'function'
318
+ )
319
+ expect(activeComponentOverrides.UnreadMessagesNotification).toBeTypeOf(
320
+ 'function'
321
+ )
322
+ })
323
+
285
324
  it('hides the actions menu (both desktop and mobile) when showChannelInfo is false', () => {
286
325
  renderWithProviders(
287
326
  <ChannelView channel={createChannel()} showChannelInfo={false} />
@@ -523,6 +523,7 @@ const ChannelViewInner: React.FC<{
523
523
  overrides={{
524
524
  Message: MessageOverride,
525
525
  MessageActions: CustomMessageActions,
526
+ UnreadMessagesNotification: () => null,
526
527
  UnreadMessagesSeparator: () => null,
527
528
  }}
528
529
  >
@@ -97,6 +97,17 @@ declare module 'stream-chat' {
97
97
  * Whether DM agent auto-replies are paused for this channel.
98
98
  */
99
99
  chatbot_paused?: boolean
100
+ /**
101
+ * Customer classification tag for this conversation (e.g. CUSTOMER_PAID).
102
+ */
103
+ customer_tag?: string
104
+ }
105
+
106
+ interface CustomMemberData {
107
+ /**
108
+ * Whether this member follows the channel's linker account.
109
+ */
110
+ is_follower?: boolean
100
111
  }
101
112
 
102
113
  interface CustomMessageData {