@linktr.ee/messaging-react 3.25.0 → 3.26.0-rc-1785465283

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-QulHlER7.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.optimizeMessagingAttachmentUrl=e.optimizeMessagingAttachmentUrl;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-Do2nl8Qo.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.optimizeMessagingAttachmentUrl=e.optimizeMessagingAttachmentUrl;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
@@ -87,6 +87,8 @@ export declare type BroadcastClickHandler = (broadcast: {
87
87
  name?: string;
88
88
  }) => void;
89
89
 
90
+ export declare type BroadcastNameResolver = (broadcastId: string) => string | undefined;
91
+
90
92
  /**
91
93
  * Build the meta line shown under the title in compact document / file
92
94
  * attachments — `EXT · SIZE` (`PDF · 379.5 KB`). Either part is dropped
@@ -210,7 +212,7 @@ export declare const ChannelView: default_2.NamedExoticComponent<ChannelViewProp
210
212
  * Props that MessagingShell passes through to ChannelView.
211
213
  * ChannelViewProps is the source of truth for these props.
212
214
  */
213
- declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'chatbotVotingEnabled' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'onBroadcastClick' | 'showChannelInfo' | 'composerInput'>;
215
+ declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'chatbotVotingEnabled' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'onBroadcastClick' | 'resolveBroadcastName' | 'showChannelInfo' | 'composerInput'>;
214
216
 
215
217
  /**
216
218
  * ChannelView component props
@@ -401,6 +403,11 @@ export declare interface ChannelViewProps {
401
403
  * Hosts own navigation so this shared package never assumes an admin URL.
402
404
  */
403
405
  onBroadcastClick?: BroadcastClickHandler;
406
+ /**
407
+ * Resolves the current campaign name for a broadcast label. The stamped
408
+ * message name remains the fallback when this returns undefined.
409
+ */
410
+ resolveBroadcastName?: BroadcastNameResolver;
404
411
  /**
405
412
  * Passed to Stream `Channel` as `SendButton`. Required for hosts that replace
406
413
  * the send control: `Channel` merges this into `ComponentContext` and an
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 c, i as u, j as L, k as h, l as p, m as d, 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, o as y, y as z, z as B, B as S, D as q, E as D, G as E, H as V, I as w } from "./index-CitR7B66.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 c, i as u, j as L, k as h, l as p, m as d, 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, o as y, y as z, z as B, B as S, D as q, E as D, G as E, H as V, I as w } from "./index-CX2t-UMh.js";
2
2
  export {
3
3
  e as ActionButton,
4
4
  t as Avatar,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "3.25.0",
3
+ "version": "3.26.0-rc-1785465283",
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.2.0",
53
+ "@linktr.ee/messaging-core": "2.3.0-rc-1785465283",
54
54
  "@linktr.ee/messaging-taxonomy": "^0.3.0",
55
55
  "@phosphor-icons/react": "^2.1.10",
56
56
  "culori": "^4.0.2"
@@ -57,6 +57,7 @@ const ChannelViewInner: React.FC<{
57
57
  showChannelInfo?: boolean
58
58
  onParticipantNameClick?: () => void
59
59
  onBroadcastClick?: ChannelViewProps['onBroadcastClick']
60
+ resolveBroadcastName?: ChannelViewProps['resolveBroadcastName']
60
61
  composerInput?: ChannelViewProps['composerInput']
61
62
  }> = ({
62
63
  onBack,
@@ -84,6 +85,7 @@ const ChannelViewInner: React.FC<{
84
85
  showChannelInfo = true,
85
86
  onParticipantNameClick,
86
87
  onBroadcastClick,
88
+ resolveBroadcastName,
87
89
  composerInput,
88
90
  }) => {
89
91
  const { channel } = useChannelStateContext()
@@ -99,6 +101,16 @@ const ChannelViewInner: React.FC<{
99
101
  const messageBroadcastClick = onBroadcastClick
100
102
  ? stableOnBroadcastClick
101
103
  : undefined
104
+ const resolveBroadcastNameRef = useRef(resolveBroadcastName)
105
+ useEffect(() => {
106
+ resolveBroadcastNameRef.current = resolveBroadcastName
107
+ }, [resolveBroadcastName])
108
+ const stableResolveBroadcastName = useCallback<
109
+ NonNullable<ChannelViewProps['resolveBroadcastName']>
110
+ >((broadcastId) => resolveBroadcastNameRef.current?.(broadcastId), [])
111
+ const messageBroadcastName = resolveBroadcastName
112
+ ? stableResolveBroadcastName
113
+ : undefined
102
114
 
103
115
  const hasVisibleMessages = channel.state.messages.some(
104
116
  (message) => message.type !== 'deleted'
@@ -140,6 +152,7 @@ const ChannelViewInner: React.FC<{
140
152
  chatbotVotingEnabled={chatbotVotingEnabled}
141
153
  viewerLanguage={viewerLanguage}
142
154
  onBroadcastClick={messageBroadcastClick}
155
+ resolveBroadcastName={messageBroadcastName}
143
156
  />
144
157
  )
145
158
 
@@ -149,6 +162,9 @@ const ChannelViewInner: React.FC<{
149
162
 
150
163
  return renderMessage(messageNode, message)
151
164
  },
165
+ // The resolver wrapper is intentionally stable; its ref reads the latest
166
+ // host resolver without changing MessageOverride's component identity.
167
+ // eslint-disable-next-line react-hooks/exhaustive-deps
152
168
  [chatbotVotingEnabled, messageBroadcastClick, renderMessage, viewerLanguage]
153
169
  )
154
170
 
@@ -308,6 +324,7 @@ export const ChannelView = React.memo<ChannelViewProps>(
308
324
  showChannelInfo = true,
309
325
  onParticipantNameClick,
310
326
  onBroadcastClick,
327
+ resolveBroadcastName,
311
328
  composerInput,
312
329
  }) => {
313
330
  // Custom send message handler that:
@@ -422,6 +439,7 @@ export const ChannelView = React.memo<ChannelViewProps>(
422
439
  showChannelInfo={showChannelInfo}
423
440
  onParticipantNameClick={onParticipantNameClick}
424
441
  onBroadcastClick={onBroadcastClick}
442
+ resolveBroadcastName={resolveBroadcastName}
425
443
  composerInput={composerInput}
426
444
  />
427
445
  </Channel>
@@ -108,6 +108,7 @@ const createMockChannel = async (
108
108
  interface TemplateProps {
109
109
  currentUser: StoryUser
110
110
  typingUser?: StoryUser
111
+ resolveBroadcastName?: (broadcastId: string) => string | undefined
111
112
  messages: Array<{
112
113
  id: string
113
114
  text: string
@@ -138,7 +139,8 @@ const TemplateInner: React.FC<{
138
139
  currentUser: StoryUser
139
140
  typingUser?: StoryUser
140
141
  messages: TemplateProps['messages']
141
- }> = ({ currentUser, typingUser, messages }) => {
142
+ resolveBroadcastName?: (broadcastId: string) => string | undefined
143
+ }> = ({ currentUser, typingUser, messages, resolveBroadcastName }) => {
142
144
  const [client] = React.useState(() => createMockStreamChatClient(currentUser))
143
145
 
144
146
  const [channel, setChannel] = React.useState<ChannelType | null>(null)
@@ -170,10 +172,11 @@ const TemplateInner: React.FC<{
170
172
  <CustomMessage
171
173
  {...props}
172
174
  onBroadcastClick={() => undefined}
175
+ resolveBroadcastName={resolveBroadcastName}
173
176
  />
174
177
  )
175
178
  }
176
- }, [])
179
+ }, [resolveBroadcastName])
177
180
 
178
181
  if (!channel) {
179
182
  return <div className="p-4">Loading...</div>
@@ -200,12 +203,14 @@ const Template: StoryFn<TemplateProps> = ({
200
203
  currentUser = storyUsers.creator,
201
204
  typingUser,
202
205
  messages,
206
+ resolveBroadcastName,
203
207
  }) => (
204
208
  <TemplateInner
205
209
  key={currentUser.id}
206
210
  currentUser={currentUser}
207
211
  typingUser={typingUser}
208
212
  messages={messages}
213
+ resolveBroadcastName={resolveBroadcastName}
209
214
  />
210
215
  )
211
216
 
@@ -302,6 +307,12 @@ BroadcastStatusNonLatest.args = {
302
307
  ],
303
308
  }
304
309
 
310
+ export const BroadcastStatusResolved: StoryFn<TemplateProps> = Template.bind({})
311
+ BroadcastStatusResolved.args = {
312
+ ...BroadcastStatus.args,
313
+ resolveBroadcastName: () => 'July 9th Class absentee',
314
+ }
315
+
305
316
  export const WithTipTag: StoryFn<TemplateProps> = Template.bind({})
306
317
  WithTipTag.args = {
307
318
  messages: [
@@ -138,4 +138,39 @@ describe('CustomMessage', () => {
138
138
  name: 'July 9th Class attendees',
139
139
  })
140
140
  })
141
+
142
+ it('prefers a resolved broadcast name over the stamped name', () => {
143
+ renderWithProviders(
144
+ <CustomMessage
145
+ resolveBroadcastName={() => 'July 9th Class absentee'}
146
+ />
147
+ )
148
+
149
+ expect(
150
+ screen.getByTestId('sent-message-broadcast-status')
151
+ ).toHaveTextContent('July 9th Class absentee')
152
+ })
153
+
154
+ it('falls back to the stamped broadcast name when resolution is unavailable', () => {
155
+ renderWithProviders(<CustomMessage resolveBroadcastName={() => undefined} />)
156
+
157
+ expect(
158
+ screen.getByTestId('sent-message-broadcast-status')
159
+ ).toHaveTextContent('July 9th Class attendees')
160
+ })
161
+
162
+ it('renders a later resolved name when the resolver value changes', () => {
163
+ const resolvedName: { current?: string } = {}
164
+ const resolveBroadcastName = () => resolvedName.current
165
+ const { rerender } = renderWithProviders(
166
+ <CustomMessage resolveBroadcastName={resolveBroadcastName} />
167
+ )
168
+
169
+ resolvedName.current = 'July 9th Class absentee'
170
+ rerender(<CustomMessage resolveBroadcastName={resolveBroadcastName} />)
171
+
172
+ expect(
173
+ screen.getByTestId('sent-message-broadcast-status')
174
+ ).toHaveTextContent('July 9th Class absentee')
175
+ })
141
176
  })
@@ -97,13 +97,21 @@ const SendingStatus = () => {
97
97
  const BroadcastStatus = ({
98
98
  broadcastId,
99
99
  broadcastName,
100
+ resolveBroadcastName,
101
+ resolvedBroadcastName,
100
102
  onBroadcastClick,
101
103
  }: {
102
104
  broadcastId: string
103
105
  broadcastName?: string
106
+ resolveBroadcastName?: (broadcastId: string) => string | undefined
107
+ resolvedBroadcastName?: string
104
108
  onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
105
109
  }) => {
106
- const name = broadcastName || 'Broadcast'
110
+ const name =
111
+ resolvedBroadcastName ||
112
+ resolveBroadcastName?.(broadcastId) ||
113
+ broadcastName ||
114
+ 'Broadcast'
107
115
  const content = (
108
116
  <>
109
117
  <span className="sent-message-broadcast-badge" aria-hidden="true">
@@ -160,8 +168,12 @@ const FailedStatus = () => (
160
168
  */
161
169
  export const SentMessageDeliveryStatus = ({
162
170
  onBroadcastClick,
171
+ resolveBroadcastName,
172
+ resolvedBroadcastName,
163
173
  }: {
164
174
  onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
175
+ resolveBroadcastName?: (broadcastId: string) => string | undefined
176
+ resolvedBroadcastName?: string
165
177
  }) => {
166
178
  const { isMyMessage, message, threadList } = useMessageContext(
167
179
  'SentMessageDeliveryStatus'
@@ -192,6 +204,8 @@ export const SentMessageDeliveryStatus = ({
192
204
  <BroadcastStatus
193
205
  broadcastId={broadcastId}
194
206
  broadcastName={broadcastName}
207
+ resolveBroadcastName={resolveBroadcastName}
208
+ resolvedBroadcastName={resolvedBroadcastName}
195
209
  onBroadcastClick={onBroadcastClick}
196
210
  />
197
211
  ) : null
@@ -55,12 +55,15 @@ type CustomMessageUIComponentProps = MessageUIComponentProps & {
55
55
  chatbotVotingEnabled?: boolean
56
56
  viewerLanguage?: string
57
57
  onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
58
+ resolveBroadcastName?: (broadcastId: string) => string | undefined
58
59
  }
59
60
 
60
61
  type CustomMessageWithContextProps = MessageContextValue & {
61
62
  chatbotVotingEnabled?: boolean
62
63
  viewerLanguage?: string
63
64
  onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
65
+ resolveBroadcastName?: (broadcastId: string) => string | undefined
66
+ resolvedBroadcastName?: string
64
67
  }
65
68
 
66
69
  const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
@@ -82,6 +85,8 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
82
85
  threadList,
83
86
  viewerLanguage,
84
87
  onBroadcastClick,
88
+ resolveBroadcastName,
89
+ resolvedBroadcastName,
85
90
  } = props
86
91
 
87
92
  const { client } = useChatContext('CustomMessage')
@@ -426,7 +431,11 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
426
431
  )}
427
432
  </div>
428
433
  )}
429
- <SentMessageDeliveryStatus onBroadcastClick={onBroadcastClick} />
434
+ <SentMessageDeliveryStatus
435
+ onBroadcastClick={onBroadcastClick}
436
+ resolveBroadcastName={resolveBroadcastName}
437
+ resolvedBroadcastName={resolvedBroadcastName}
438
+ />
430
439
  {showReplyCountButton && (
431
440
  <MessageRepliesCountButton
432
441
  onClick={handleOpenThread}
@@ -447,11 +456,24 @@ const MemoizedCustomMessage = React.memo(
447
456
  if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false
448
457
  if (prev.viewerLanguage !== next.viewerLanguage) return false
449
458
  if (prev.onBroadcastClick !== next.onBroadcastClick) return false
459
+ if (prev.resolveBroadcastName !== next.resolveBroadcastName) return false
460
+ if (prev.resolvedBroadcastName !== next.resolvedBroadcastName) return false
450
461
  return areMessageUIPropsEqual(prev, next)
451
462
  }
452
463
  ) as typeof CustomMessageWithContext
453
464
 
454
465
  export const CustomMessage = (props: CustomMessageUIComponentProps) => {
455
466
  const messageContext = useMessageContext('CustomMessage')
456
- return <MemoizedCustomMessage {...messageContext} {...props} />
467
+ const broadcastId = messageContext.message.metadata?.broadcast_id
468
+ const resolvedBroadcastName = broadcastId
469
+ ? props.resolveBroadcastName?.(broadcastId)
470
+ : undefined
471
+
472
+ return (
473
+ <MemoizedCustomMessage
474
+ {...messageContext}
475
+ {...props}
476
+ resolvedBroadcastName={resolvedBroadcastName}
477
+ />
478
+ )
457
479
  }
@@ -39,6 +39,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
39
39
  renderChannelActions,
40
40
  onParticipantNameClick,
41
41
  onBroadcastClick,
42
+ resolveBroadcastName,
42
43
  renderMessage,
43
44
  onMessageLinkClick,
44
45
  showChannelInfo,
@@ -265,6 +266,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
265
266
  renderChannelActions={renderChannelActions}
266
267
  onParticipantNameClick={onParticipantNameClick}
267
268
  onBroadcastClick={onBroadcastClick}
269
+ resolveBroadcastName={resolveBroadcastName}
268
270
  renderMessage={renderMessage}
269
271
  onMessageLinkClick={onMessageLinkClick}
270
272
  showChannelInfo={showChannelInfo}
package/src/index.ts CHANGED
@@ -61,6 +61,7 @@ export type {
61
61
  MessagingCapabilities,
62
62
  MessageLinkClickHandler,
63
63
  BroadcastClickHandler,
64
+ BroadcastNameResolver,
64
65
  Participant,
65
66
  LockedAttachmentSource,
66
67
  } from './types'
package/src/types.ts CHANGED
@@ -41,6 +41,8 @@ export type BroadcastClickHandler = (broadcast: {
41
41
  name?: string
42
42
  }) => void
43
43
 
44
+ export type BroadcastNameResolver = (broadcastId: string) => string | undefined
45
+
44
46
  export type ChannelPreviewProps = ChannelPreviewUIComponentProps & {
45
47
  selectedChannel?: Channel | null
46
48
  onChannelSelect: (channel: Channel) => void
@@ -373,6 +375,12 @@ export interface ChannelViewProps {
373
375
  */
374
376
  onBroadcastClick?: BroadcastClickHandler
375
377
 
378
+ /**
379
+ * Resolves the current campaign name for a broadcast label. The stamped
380
+ * message name remains the fallback when this returns undefined.
381
+ */
382
+ resolveBroadcastName?: BroadcastNameResolver
383
+
376
384
  /**
377
385
  * Passed to Stream `Channel` as `SendButton`. Required for hosts that replace
378
386
  * the send control: `Channel` merges this into `ComponentContext` and an
@@ -442,6 +450,7 @@ export type ChannelViewPassthroughProps = Pick<
442
450
  | 'renderMessage'
443
451
  | 'onMessageLinkClick'
444
452
  | 'onBroadcastClick'
453
+ | 'resolveBroadcastName'
445
454
  | 'showChannelInfo'
446
455
  | 'composerInput'
447
456
  >