@linktr.ee/messaging-react 4.1.5-rc-1786935540 → 4.1.5-rc-1786947787

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-CCcZf30n.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.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.RichCard=e.RichCard;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.useMessaging=e.useMessaging;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-D0h8u2Iq.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.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.RichCard=e.RichCard;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.useMessaging=e.useMessaging;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -208,7 +208,7 @@ export declare const ChannelView: default_2.NamedExoticComponent<ChannelViewProp
208
208
  * Props that MessagingShell passes through to ChannelView.
209
209
  * ChannelViewProps is the source of truth for these props.
210
210
  */
211
- declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'onOutboundClick' | 'resolveOutbound' | 'showChannelInfo' | 'composerInput'>;
211
+ declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'onOutboundClick' | 'resolveOutbound' | 'showChannelInfo' | 'composerInput' | 'attachmentPreviewList'>;
212
212
 
213
213
  /**
214
214
  * ChannelView component props
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, b as t, C as i, c as n, d as o, e as m, F as r, f as l, L as g, h as c, M, i as h, j as L, k as u, l as d, R as p, m as C, n as v, p as A, q as k, s as F, t as b, u as P, v as f, w as x, o as y, x as z, y as S, z as q, B, D, E, G as R } from "./index-Bia73RlU.js";
1
+ import { a as e, b as t, C as i, c as n, d as o, e as m, F as r, f as l, L as g, h as c, M, i as h, j as L, k as u, l as d, R as p, m as C, n as v, p as A, q as k, s as F, t as b, u as P, v as f, w as x, o as y, x as z, y as S, z as q, B, D, E, G as R } from "./index-CBGh9Qyj.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": "4.1.5-rc-1786935540",
3
+ "version": "4.1.5-rc-1786947787",
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
  "chromatic:local": "yarn storybook:build && chromatic"
51
51
  },
52
52
  "dependencies": {
53
- "@linktr.ee/messaging-core": "2.4.0-rc-1786935540",
53
+ "@linktr.ee/messaging-core": "2.4.0-rc-1786947787",
54
54
  "@linktr.ee/messaging-taxonomy": "^0.10.0",
55
55
  "@phosphor-icons/react": "^2.1.10"
56
56
  },
@@ -60,7 +60,6 @@ vi.mock('./MessageTag', () => ({
60
60
  isMediaAttachmentMessage: () => false,
61
61
  isTextAttachmentMessage: () => false,
62
62
  isTipOnlyMessage: () => false,
63
- hasPaidDeliveryTag: () => false,
64
63
  }))
65
64
 
66
65
  vi.mock('./LockedAttachment', () => ({
@@ -67,15 +67,6 @@ const isTipOrPaidMessage = (message: LocalMessage): boolean => {
67
67
  return isTipMessage(message) || isPaidMessage(message)
68
68
  }
69
69
 
70
- /** Check if the footer tag on this message already reads "Delivered with …" */
71
- export const hasPaidDeliveryTag = (message: LocalMessage): boolean => {
72
- return (
73
- isTipOrPaidMessage(message) &&
74
- !isTipOnlyMessage(message) &&
75
- !!message.metadata?.amount_text
76
- )
77
- }
78
-
79
70
  /** Check if a message is a tip/paid-only message (no text) */
80
71
  export const isTipOnlyMessage = (message: LocalMessage): boolean => {
81
72
  return isTipOrPaidMessage(message) && !message.text?.trim()
@@ -391,109 +391,6 @@ describe('SentMessageDeliveryStatus', () => {
391
391
  expect(screen.queryByTestId('sending-slot')).not.toBeInTheDocument()
392
392
  })
393
393
 
394
- it.each([
395
- ['paid', 'MESSAGE_PAID'],
396
- ['tip', 'MESSAGE_TIP'],
397
- ])('does not render the delivery stamp on a %s message', (_label, type) => {
398
- mockedUseMessageContext.mockReturnValue({
399
- message: {
400
- id: 'own-2',
401
- text: 'thanks!',
402
- metadata: { custom_type: type, amount_text: '$10.00' },
403
- },
404
- isMyMessage: () => true,
405
- threadList: false,
406
- } as never)
407
-
408
- renderWithProviders(<SentMessageDeliveryStatus />)
409
-
410
- for (const slot of TERMINAL_SLOTS) {
411
- expect(screen.queryByTestId(slot)).not.toBeInTheDocument()
412
- }
413
- expect(screen.queryByTestId('sending-slot')).not.toBeInTheDocument()
414
- })
415
-
416
- it('keeps the delivery stamp on a textless paid message, which has no footer tag', () => {
417
- mockedUseMessageContext.mockReturnValue({
418
- message: {
419
- id: 'own-2',
420
- metadata: { custom_type: 'MESSAGE_PAID', amount_text: '$10.00' },
421
- },
422
- isMyMessage: () => true,
423
- threadList: false,
424
- } as never)
425
-
426
- renderWithProviders(<SentMessageDeliveryStatus />)
427
-
428
- for (const slot of TERMINAL_SLOTS) {
429
- expect(screen.getByTestId(slot)).toHaveTextContent(/delivered/i)
430
- }
431
- })
432
-
433
- it('does not render the sending stamp on a paid message', () => {
434
- mockedUseMessageContext.mockReturnValue({
435
- message: {
436
- id: 'own-2',
437
- status: 'sending',
438
- text: 'thanks!',
439
- metadata: { custom_type: 'MESSAGE_PAID', amount_text: '$10.00' },
440
- },
441
- isMyMessage: () => true,
442
- threadList: false,
443
- } as never)
444
-
445
- renderWithProviders(<SentMessageDeliveryStatus />)
446
-
447
- expect(screen.queryByTestId('sending-slot')).not.toBeInTheDocument()
448
- expect(
449
- screen.queryByTestId('sent-message-sending-status')
450
- ).not.toBeInTheDocument()
451
- })
452
-
453
- it('keeps the failed and outbound stamps on a paid message', () => {
454
- mockedUseMessageContext.mockReturnValue({
455
- message: {
456
- id: 'own-2',
457
- status: 'failed',
458
- type: 'regular',
459
- text: 'thanks!',
460
- metadata: { custom_type: 'MESSAGE_PAID', amount_text: '$10.00' },
461
- },
462
- isMyMessage: () => true,
463
- threadList: false,
464
- } as never)
465
-
466
- const { rerender } = renderWithProviders(<SentMessageDeliveryStatus />)
467
-
468
- expect(screen.getByTestId('sent-message-failed-status')).toHaveTextContent(
469
- /failed to send/i
470
- )
471
-
472
- mockedUseMessageContext.mockReturnValue({
473
- message: {
474
- id: 'own-2',
475
- text: 'thanks!',
476
- metadata: {
477
- custom_type: 'MESSAGE_PAID',
478
- amount_text: '$10.00',
479
- outbound_id: 'outbound-1',
480
- },
481
- },
482
- isMyMessage: () => true,
483
- threadList: false,
484
- } as never)
485
- rerender(
486
- <SentMessageDeliveryStatus
487
- resolvedOutbound={{ id: 'automation-1', name: 'July 9th Class' }}
488
- />
489
- )
490
-
491
- expect(
492
- screen.getByTestId('sent-message-outbound-status')
493
- ).toHaveTextContent('July 9th Class')
494
- expect(screen.queryByText('•')).not.toBeInTheDocument()
495
- })
496
-
497
394
  it('does not render failure status for a received message or thread message', () => {
498
395
  mockedUseMessageContext.mockReturnValue({
499
396
  message: { id: 'own-1', status: 'failed', type: 'regular' },
@@ -13,8 +13,6 @@ import {
13
13
 
14
14
  import type { OutboundClickHandler, ResolvedOutbound } from '../../types'
15
15
 
16
- import { hasPaidDeliveryTag } from './MessageTag'
17
-
18
16
  /**
19
17
  * Message status stamps for sending and terminal `MessageStatus` states
20
18
  * (sent / delivered / read), plus failed messages.
@@ -161,10 +159,6 @@ const FailedStatus = () => (
161
159
  * latest-message-in-thread gate; failed messages bypass `MessageStatus`
162
160
  * because it has no failed slot and are shown on every own, non-thread
163
161
  * failed message.
164
- *
165
- * Messages whose footer tag already reads "Delivered with $10 message" skip
166
- * this label so delivery is only claimed once (MES-1480); failed and broadcast
167
- * stamps still apply.
168
162
  */
169
163
  export const SentMessageDeliveryStatus = ({
170
164
  onOutboundClick,
@@ -205,7 +199,7 @@ export const SentMessageDeliveryStatus = ({
205
199
  />
206
200
  ) : null
207
201
 
208
- const messageStatus = hasPaidDeliveryTag(message) ? null : (
202
+ const messageStatus = (
209
203
  <MessageStatus
210
204
  MessageSentStatus={DeliveredStatus}
211
205
  MessageDeliveredStatus={DeliveredStatus}
@@ -221,7 +215,7 @@ export const SentMessageDeliveryStatus = ({
221
215
  return (
222
216
  <span className="sent-message-status-row">
223
217
  {messageStatus}
224
- {messageStatus && isLatestRealMessage && (
218
+ {isLatestRealMessage && (
225
219
  <span className="sent-message-outbound-separator" aria-hidden="true">
226
220
  •
227
221
  </span>
@@ -125,6 +125,26 @@ describe('MessagingShell', () => {
125
125
  })
126
126
  })
127
127
 
128
+ it('forwards attachmentPreviewList to the selected channel view', async () => {
129
+ queryChannelsMock.mockResolvedValue([makeChannel('existing-1')])
130
+ const AttachmentPreviewList = () => <div>staged attachment</div>
131
+
132
+ renderWithProviders(
133
+ <MessagingShell
134
+ initialParticipantFilter="other-1"
135
+ attachmentPreviewList={AttachmentPreviewList}
136
+ />
137
+ )
138
+
139
+ await waitFor(() => {
140
+ expect(screen.getByTestId('channel-view')).toBeInTheDocument()
141
+ })
142
+
143
+ expect(capturedChannelViewProps.attachmentPreviewList).toBe(
144
+ AttachmentPreviewList
145
+ )
146
+ })
147
+
128
148
  it('calls onExitConversation and renders "Conversation ended" when the user leaves the conversation', async () => {
129
149
  queryChannelsMock.mockResolvedValue([makeChannel('existing-1')])
130
150
  const onExit = vi.fn()
@@ -43,6 +43,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
43
43
  onMessageLinkClick,
44
44
  showChannelInfo,
45
45
  composerInput,
46
+ attachmentPreviewList,
46
47
  }) => {
47
48
  const {
48
49
  client,
@@ -269,6 +270,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
269
270
  onMessageLinkClick={onMessageLinkClick}
270
271
  showChannelInfo={showChannelInfo}
271
272
  composerInput={composerInput}
273
+ attachmentPreviewList={attachmentPreviewList}
272
274
  />
273
275
  </div>
274
276
  </div>
package/src/types.ts CHANGED
@@ -453,6 +453,7 @@ export type ChannelViewPassthroughProps = Pick<
453
453
  | 'resolveOutbound'
454
454
  | 'showChannelInfo'
455
455
  | 'composerInput'
456
+ | 'attachmentPreviewList'
456
457
  >
457
458
 
458
459
  /**