@linktr.ee/messaging-react 3.9.0-rc-1783580190 → 3.9.1-rc-1783576271

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.
Files changed (88) hide show
  1. package/dist/Card-CyBRO0Ex.cjs +2 -0
  2. package/dist/Card-CyBRO0Ex.cjs.map +1 -0
  3. package/dist/Card-DYNxwKX6.js +132 -0
  4. package/dist/Card-DYNxwKX6.js.map +1 -0
  5. package/dist/Card-DmfP-4oF.cjs +2 -0
  6. package/dist/Card-DmfP-4oF.cjs.map +1 -0
  7. package/dist/Card-PBfzY620.cjs +2 -0
  8. package/dist/Card-PBfzY620.cjs.map +1 -0
  9. package/dist/Card-dZkL-om-.js +163 -0
  10. package/dist/Card-dZkL-om-.js.map +1 -0
  11. package/dist/Card-xR3OTXRB.js +107 -0
  12. package/dist/Card-xR3OTXRB.js.map +1 -0
  13. package/dist/LockedThumbnail-BblFdDJp.js +220 -0
  14. package/dist/LockedThumbnail-BblFdDJp.js.map +1 -0
  15. package/dist/LockedThumbnail-eE8ljauK.cjs +2 -0
  16. package/dist/LockedThumbnail-eE8ljauK.cjs.map +1 -0
  17. package/dist/assets/index.css +1 -1
  18. package/dist/index-Bxezkdl6.cjs +2 -0
  19. package/dist/index-Bxezkdl6.cjs.map +1 -0
  20. package/dist/{index-CmVOs9Jy.js → index-FY6hmphi.js} +1198 -1226
  21. package/dist/index-FY6hmphi.js.map +1 -0
  22. package/dist/index.cjs +1 -1
  23. package/dist/index.d.ts +98 -161
  24. package/dist/index.js +1 -1
  25. package/dist/testing.d.ts +0 -1
  26. package/package.json +2 -2
  27. package/src/components/ChannelList/CustomChannelPreview.test.tsx +0 -95
  28. package/src/components/ChannelList/CustomChannelPreview.tsx +9 -21
  29. package/src/components/CustomMessage/CustomMessage.stories.tsx +1 -54
  30. package/src/components/CustomMessage/MessageTag.tsx +0 -8
  31. package/src/components/CustomMessage/SentMessageDeliveryStatus.test.tsx +29 -11
  32. package/src/components/CustomMessage/SentMessageDeliveryStatus.tsx +22 -26
  33. package/src/components/CustomMessage/context.tsx +1 -1
  34. package/src/components/CustomMessage/index.tsx +42 -76
  35. package/src/components/CustomMessageInput/CustomMessageInput.stories.tsx +3 -5
  36. package/src/components/LockedAttachment/LockedAttachment.stories.tsx +450 -0
  37. package/src/components/LockedAttachment/components/Composer/Card.tsx +221 -0
  38. package/src/components/LockedAttachment/components/Composer/index.ts +2 -0
  39. package/src/components/LockedAttachment/components/Received/Card.tsx +191 -0
  40. package/src/components/{CustomMessage/LockedAttachment/components/Media → LockedAttachment/components/Received}/CardActions.tsx +2 -9
  41. package/src/components/LockedAttachment/components/Received/index.ts +2 -0
  42. package/src/components/LockedAttachment/components/Sent/Card.tsx +177 -0
  43. package/src/components/LockedAttachment/components/Sent/index.ts +2 -0
  44. package/src/components/{CustomMessage/LockedAttachment → LockedAttachment}/components/_shared/CardBody.tsx +7 -8
  45. package/src/components/{CustomMessage/LockedAttachment → LockedAttachment}/components/_shared/GalleryThumbnail.tsx +39 -31
  46. package/src/components/LockedAttachment/components/_shared/LockBadge.tsx +39 -0
  47. package/src/components/{CustomMessage/LockedAttachment/components/_shared/MediaShell.tsx → LockedAttachment/components/_shared/LockedCardShell.tsx} +8 -8
  48. package/src/components/{CustomMessage/LockedAttachment/components/_shared/SingleThumbnail.tsx → LockedAttachment/components/_shared/LockedThumbnail.tsx} +7 -11
  49. package/src/components/LockedAttachment/index.tsx +63 -0
  50. package/src/components/LockedAttachment/types.ts +51 -0
  51. package/src/index.ts +8 -3
  52. package/src/stream-custom-data.ts +0 -1
  53. package/src/styles.css +0 -12
  54. package/src/types.ts +1 -1
  55. package/dist/Card-415OfRhw.cjs +0 -2
  56. package/dist/Card-415OfRhw.cjs.map +0 -1
  57. package/dist/Card-Q9e8pbMP.js +0 -694
  58. package/dist/Card-Q9e8pbMP.js.map +0 -1
  59. package/dist/Card-dg4NGPoC.cjs +0 -2
  60. package/dist/Card-dg4NGPoC.cjs.map +0 -1
  61. package/dist/Card-qS17qnN0.js +0 -103
  62. package/dist/Card-qS17qnN0.js.map +0 -1
  63. package/dist/LoadingDots-Ct3WmVlT.js +0 -59
  64. package/dist/LoadingDots-Ct3WmVlT.js.map +0 -1
  65. package/dist/LoadingDots-D9GGphgM.cjs +0 -2
  66. package/dist/LoadingDots-D9GGphgM.cjs.map +0 -1
  67. package/dist/index-ChRwg_g6.cjs +0 -2
  68. package/dist/index-ChRwg_g6.cjs.map +0 -1
  69. package/dist/index-CmVOs9Jy.js.map +0 -1
  70. package/src/components/CustomMessage/LockedAttachment/LockedAttachment.stories.tsx +0 -541
  71. package/src/components/CustomMessage/LockedAttachment/LockedAttachment.test.tsx +0 -117
  72. package/src/components/CustomMessage/LockedAttachment/components/Media/Card.tsx +0 -358
  73. package/src/components/CustomMessage/LockedAttachment/components/Media/types.ts +0 -79
  74. package/src/components/CustomMessage/LockedAttachment/components/Text/Card.tsx +0 -153
  75. package/src/components/CustomMessage/LockedAttachment/components/Text/types.ts +0 -58
  76. package/src/components/CustomMessage/LockedAttachment/components/_shared/CardThumbnail.tsx +0 -92
  77. package/src/components/CustomMessage/LockedAttachment/components/_shared/LoadingDots.tsx +0 -36
  78. package/src/components/CustomMessage/LockedAttachment/components/_shared/LockBadge.tsx +0 -63
  79. package/src/components/CustomMessage/LockedAttachment/components/_shared/PreviewToggle.tsx +0 -58
  80. package/src/components/CustomMessage/LockedAttachment/components/_shared/PriceLockRow.tsx +0 -21
  81. package/src/components/CustomMessage/LockedAttachment/components/_shared/PurchaseStatusBadge.tsx +0 -74
  82. package/src/components/CustomMessage/LockedAttachment/components/_shared/SkeletonTextLines.tsx +0 -29
  83. package/src/components/CustomMessage/LockedAttachment/components/_shared/TextShell.tsx +0 -28
  84. package/src/components/CustomMessage/LockedAttachment/components/_shared/usePreviewToggle.test.ts +0 -67
  85. package/src/components/CustomMessage/LockedAttachment/components/_shared/usePreviewToggle.ts +0 -89
  86. package/src/components/CustomMessage/LockedAttachment/components/_shared/useReceivedSource.ts +0 -83
  87. package/src/components/CustomMessage/LockedAttachment/index.tsx +0 -105
  88. package/src/components/CustomMessage/LockedAttachment/types.ts +0 -44
@@ -1,7 +1,6 @@
1
1
  import React from 'react'
2
2
  import {
3
3
  useChannelStateContext,
4
- useChatContext,
5
4
  useMessageContext,
6
5
  } from 'stream-chat-react'
7
6
  import { beforeEach, describe, expect, it, vi } from 'vitest'
@@ -13,14 +12,13 @@ import { SentMessageDeliveryStatus } from './SentMessageDeliveryStatus'
13
12
  // stream-chat-react's `MessageStatus` owns the outer gating (own message, not
14
13
  // error, not in a thread) and only exposes a terminal state once a message is
15
14
  // stored — Stream's tested code. What this component owns is the "Delivered"
16
- // label wired into the terminal slots (sent/delivered/read), its "last own
17
- // message" gate derived from live channel state, and suppressing the sending
18
- // spinner. Mock `MessageStatus` to render the slots it was handed, and the
19
- // context hooks the label reads.
15
+ // label wired into the terminal slots (sent/delivered/read), its "latest
16
+ // message in the thread" gate derived from live channel state, and suppressing
17
+ // the sending spinner. Mock `MessageStatus` to render the slots it was handed,
18
+ // and the context hooks the label reads.
20
19
  vi.mock('stream-chat-react', () => ({
21
20
  useMessageContext: vi.fn(),
22
21
  useChannelStateContext: vi.fn(),
23
- useChatContext: vi.fn(),
24
22
  MessageStatus: ({
25
23
  MessageSentStatus,
26
24
  MessageDeliveredStatus,
@@ -46,10 +44,10 @@ vi.mock('stream-chat-react', () => ({
46
44
 
47
45
  const mockedUseMessageContext = vi.mocked(useMessageContext)
48
46
  const mockedUseChannelStateContext = vi.mocked(useChannelStateContext)
49
- const mockedUseChatContext = vi.mocked(useChatContext)
50
47
 
51
48
  // A run where the viewer ('me') sent the first and last messages, with an
52
- // incoming message in between — the case that broke the memo-based approach.
49
+ // incoming message in between — the label must sit on the last message ('own-2')
50
+ // and clear from the earlier one.
53
51
  const CHANNEL_MESSAGES = [
54
52
  { id: 'own-1', user: { id: 'me' } },
55
53
  { id: 'their-1', user: { id: 'them' } },
@@ -60,13 +58,12 @@ const TERMINAL_SLOTS = ['sent-slot', 'delivered-slot', 'read-slot'] as const
60
58
 
61
59
  describe('SentMessageDeliveryStatus', () => {
62
60
  beforeEach(() => {
63
- mockedUseChatContext.mockReturnValue({ client: { user: { id: 'me' } } } as never)
64
61
  mockedUseChannelStateContext.mockReturnValue({
65
62
  messages: CHANNEL_MESSAGES,
66
63
  } as never)
67
64
  })
68
65
 
69
- it('renders "Delivered" in every terminal slot for the last own message', () => {
66
+ it('renders "Delivered" in every terminal slot for the last message in the thread', () => {
70
67
  // delivered/read fire ahead of sent in receipt channels, so all three
71
68
  // must show the label — never Stream's default delivered icon / read
72
69
  // avatars.
@@ -83,7 +80,7 @@ describe('SentMessageDeliveryStatus', () => {
83
80
  }
84
81
  })
85
82
 
86
- it('renders nothing for an earlier own message even though one is the last own message', () => {
83
+ it('renders nothing for an earlier own message once a later message exists', () => {
87
84
  mockedUseMessageContext.mockReturnValue({
88
85
  message: { id: 'own-1' },
89
86
  } as never)
@@ -95,6 +92,27 @@ describe('SentMessageDeliveryStatus', () => {
95
92
  }
96
93
  })
97
94
 
95
+ it('renders nothing for an own message once a reply arrives after it', () => {
96
+ // 'own-2' was the viewer's last sent message, but 'their-1' is now the
97
+ // latest message in the thread — the label must clear from the bubble.
98
+ mockedUseChannelStateContext.mockReturnValue({
99
+ messages: [
100
+ { id: 'own-1', user: { id: 'me' } },
101
+ { id: 'own-2', user: { id: 'me' } },
102
+ { id: 'their-1', user: { id: 'them' } },
103
+ ],
104
+ } as never)
105
+ mockedUseMessageContext.mockReturnValue({
106
+ message: { id: 'own-2' },
107
+ } as never)
108
+
109
+ renderWithProviders(<SentMessageDeliveryStatus />)
110
+
111
+ for (const slot of TERMINAL_SLOTS) {
112
+ expect(screen.getByTestId(slot)).toBeEmptyDOMElement()
113
+ }
114
+ })
115
+
98
116
  it('always suppresses the sending spinner', () => {
99
117
  mockedUseMessageContext.mockReturnValue({
100
118
  message: { id: 'own-2' },
@@ -3,7 +3,6 @@ import { useMemo } from 'react'
3
3
  import {
4
4
  MessageStatus,
5
5
  useChannelStateContext,
6
- useChatContext,
7
6
  useMessageContext,
8
7
  } from 'stream-chat-react'
9
8
 
@@ -15,21 +14,23 @@ import {
15
14
  *
16
15
  * 1. `MessageStatus` picks its `delivered`/`read` branches ahead of `sent`
17
16
  * whenever Stream has `deliveredTo`/`readBy`, and — unlike `sent` — those
18
- * branches aren't gated to the last own message. So we override all three
17
+ * branches aren't gated to the last message. So we override all three
19
18
  * terminal slots with this same label (never Stream's default delivered
20
- * icon / read avatars — Read is out of scope) and re-apply the "last own
21
- * message" gate ourselves.
19
+ * icon / read avatars — Read is out of scope) and re-apply the "latest
20
+ * message in the thread" gate ourselves: the label only shows beneath the
21
+ * viewer's sent message while it is still the last message in the channel,
22
+ * and disappears as soon as a reply arrives after it.
22
23
  *
23
- * 2. We derive "last own message" from **live channel state**, not the
24
- * message context's `lastOwnMessage`. Stream's `Message` is memoised by
25
- * `areMessagePropsEqual`, which does not compare `lastOwnMessage`; a
26
- * previous own row whose message/grouping props are unchanged (e.g. after
27
- * an intervening incoming message) never re-renders, so its context
28
- * `lastOwnMessage` goes stale and the old bubble would keep showing
29
- * "Delivered" beside the new one. `useChannelStateContext` gets a fresh
30
- * `messages` array on every new message and, being a context, re-renders
31
- * this leaf straight through the stale `Message`/`MessageStatus` memos —
32
- * so the label reliably hops to the newest own message.
24
+ * 2. We derive "latest message" from **live channel state**, not the message
25
+ * context's `lastOwnMessage`/`lastReceivedId`. Stream's `Message` is
26
+ * memoised by `areMessagePropsEqual`, which does not compare those props;
27
+ * a previous own row whose message/grouping props are unchanged (e.g.
28
+ * after an intervening incoming message) never re-renders, so the old
29
+ * bubble would keep showing "Delivered" beside the new one.
30
+ * `useChannelStateContext` gets a fresh `messages` array on every new
31
+ * message and, being a context, re-renders this leaf straight through the
32
+ * stale `Message`/`MessageStatus` memos — so the label reliably clears
33
+ * once a reply lands.
33
34
  *
34
35
  * Rendered inside stream's `.str-chat__message-status` span, which supplies
35
36
  * the flex layout; icon and copy are styled via that span in `styles.css`.
@@ -37,18 +38,13 @@ import {
37
38
  const DeliveredStatus = () => {
38
39
  const { message } = useMessageContext('SentMessageDeliveryStatus')
39
40
  const { messages } = useChannelStateContext('SentMessageDeliveryStatus')
40
- const { client } = useChatContext('SentMessageDeliveryStatus')
41
41
 
42
- const ownUserId = client.user?.id
43
- const lastOwnMessageId = useMemo(() => {
44
- if (!ownUserId || !messages) return undefined
45
- for (let i = messages.length - 1; i >= 0; i -= 1) {
46
- if (messages[i].user?.id === ownUserId) return messages[i].id
47
- }
48
- return undefined
49
- }, [messages, ownUserId])
42
+ const lastMessageId = useMemo(
43
+ () => messages?.[messages.length - 1]?.id,
44
+ [messages]
45
+ )
50
46
 
51
- if (message.id !== lastOwnMessageId) {
47
+ if (message.id !== lastMessageId) {
52
48
  return null
53
49
  }
54
50
 
@@ -73,8 +69,8 @@ const NoStatus = () => null
73
69
  * terminal (sending/sent/delivered/read) state once the message is stored.
74
70
  * Scope is "Delivered" only: the sending spinner is suppressed and all
75
71
  * terminal states render {@link DeliveredStatus}, which supplies the label
76
- * and the last-own-message gate (see there for why the gate is computed from
77
- * live channel state rather than the context's `lastOwnMessage`).
72
+ * and the latest-message-in-thread gate (see there for why the gate is
73
+ * computed from live channel state rather than the context's props).
78
74
  */
79
75
  export const SentMessageDeliveryStatus = () => (
80
76
  <MessageStatus
@@ -1,6 +1,6 @@
1
1
  import { createContext, useContext } from 'react'
2
2
 
3
- import { defaultLockedAttachmentContextValue, type LockedAttachmentContextValue } from './LockedAttachment/types'
3
+ import { defaultLockedAttachmentContextValue, type LockedAttachmentContextValue } from '../LockedAttachment/types'
4
4
 
5
5
  export interface CustomMessageRegistry {
6
6
  LockedAttachment: LockedAttachmentContextValue
@@ -32,17 +32,17 @@ import {
32
32
  import { useMessageVote } from '../../hooks/useMessageVote'
33
33
  import { getMessageDisplayText } from '../../utils/getMessageDisplayText'
34
34
  import { Avatar } from '../Avatar'
35
+ import LockedAttachment from '../LockedAttachment'
35
36
  import { isLinkAttachment } from '../MediaMessage'
36
- import { bubbleGroupPositionFromStream as messageAttachmentGroupPositionFromStream } from '../MessageAttachment'
37
+ import {
38
+ bubbleGroupPositionFromStream as messageAttachmentGroupPositionFromStream,
39
+ } from '../MessageAttachment'
37
40
 
38
41
  import { useCustomMessage } from './context'
39
- import LockedAttachment from './LockedAttachment'
40
42
  import {
41
43
  MessageTag,
42
44
  isAttachmentMessage,
43
45
  isChatbotMessage,
44
- isMediaAttachmentMessage,
45
- isTextAttachmentMessage,
46
46
  isTipOnlyMessage,
47
47
  } from './MessageTag'
48
48
  import { MessageVoteButtons } from './MessageVoteButtons'
@@ -145,12 +145,13 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
145
145
  (total, segment) => total + segment.attachments.length,
146
146
  0
147
147
  ) === (finalAttachments?.length ?? 0)
148
- const streamAttachmentGroupPosition =
149
- messageAttachmentGroupPositionFromStream({
148
+ const streamAttachmentGroupPosition = messageAttachmentGroupPositionFromStream(
149
+ {
150
150
  endOfGroup,
151
151
  firstOfGroup,
152
152
  groupedByUser,
153
- })
153
+ }
154
+ )
154
155
 
155
156
  if (isDateSeparatorMessage(message)) {
156
157
  return null
@@ -225,26 +226,6 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
225
226
  !isAIGenerated &&
226
227
  !isChatbot
227
228
 
228
- const sharedLockedTextProps = {
229
- contentType: 'text' as const,
230
- amountText: message.metadata?.amount_text,
231
- paymentStatus: message.metadata?.payment_status,
232
- renderedText: message.text && (
233
- <MessageText message={displayMessage} renderText={renderText} />
234
- ),
235
- }
236
- const sharedLockedMediaProps = {
237
- contentType: 'media' as const,
238
- title: message.metadata?.attachment_title,
239
- mimeType: message.metadata?.attachment_mime_type,
240
- thumbnailUrl: message.metadata?.attachment_thumbnail,
241
- amountText: message.metadata?.amount_text,
242
- detail: message.metadata?.attachment_detail,
243
- paymentStatus: message.metadata?.payment_status,
244
- onFetchSource: onFetchSource
245
- ? () => onFetchSource(message, channel)
246
- : undefined,
247
- }
248
229
  return (
249
230
  <>
250
231
  {editing && (
@@ -295,61 +276,43 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
295
276
  marginInlineStart: 0,
296
277
  }}
297
278
  >
298
- {isTipOnly ? (
299
- <MessageTag message={message} standalone />
300
- ) : isTextAttachmentMessage(message) ? (
279
+ {isAttachment ? (
301
280
  <div className="str-chat__message-bubble-wrapper">
302
- <div className="flex items-center gap-2">
303
- {isMine && MessageActions && <MessageActions />}
304
- {isMine ? (
305
- <LockedAttachment
306
- {...sharedLockedTextProps}
307
- isMine={true}
308
- />
309
- ) : (
310
- <LockedAttachment
311
- {...sharedLockedTextProps}
312
- isMine={false}
313
- isUnlocking={isUnlocking(message.id)}
314
- onUnlockClick={() => onUnlockClick?.(message, channel)}
315
- />
316
- )}
317
- {!isMine && MessageActions && <MessageActions />}
318
- </div>
319
- </div>
320
- ) : isMediaAttachmentMessage(message) ? (
321
- <div className="str-chat__message-bubble-wrapper">
322
- <div className="flex items-center gap-2">
323
- {isMine && MessageActions && <MessageActions />}
324
- {isMine ? (
325
- <LockedAttachment
326
- {...sharedLockedMediaProps}
327
- isMine={true}
328
- onPreviewClick={() =>
329
- onUnlockClick
330
- ? onUnlockClick(message, channel)
331
- : undefined
281
+ {isMine ? (
282
+ <div className="flex items-center gap-2">
283
+ {MessageActions && <MessageActions />}
284
+ <LockedAttachment.Sent
285
+ title={message.metadata?.attachment_title}
286
+ mimeType={message.metadata?.attachment_mime_type}
287
+ thumbnailUrl={message.metadata?.attachment_thumbnail}
288
+ amountText={message.metadata?.amount_text}
289
+ detail={message.metadata?.attachment_detail}
290
+ paymentStatus={message.metadata?.payment_status}
291
+ onPreviewClick={() => onUnlockClick?.(message, channel)}
292
+ onFetchSource={async () =>
293
+ await onFetchSource?.(message, channel)
332
294
  }
333
295
  />
334
- ) : (
335
- <LockedAttachment
336
- {...sharedLockedMediaProps}
337
- isMine={false}
296
+ </div>
297
+ ) : (
298
+ <div className="flex items-center gap-2">
299
+ <LockedAttachment.Received
300
+ title={message.metadata?.attachment_title}
301
+ mimeType={message.metadata?.attachment_mime_type}
302
+ thumbnailUrl={message.metadata?.attachment_thumbnail}
303
+ amountText={message.metadata?.amount_text}
304
+ detail={message.metadata?.attachment_detail}
305
+ paymentStatus={message.metadata?.payment_status}
338
306
  isUnlocking={isUnlocking(message.id)}
339
- onUnlockClick={() =>
340
- onUnlockClick
341
- ? onUnlockClick(message, channel)
342
- : undefined
343
- }
344
- onDownloadClick={() =>
345
- onDownloadClick
346
- ? onDownloadClick(message, channel)
347
- : undefined
307
+ onUnlockClick={() => onUnlockClick?.(message, channel)}
308
+ onFetchSource={async () =>
309
+ await onFetchSource?.(message, channel)
348
310
  }
311
+ onDownloadClick={() => onDownloadClick?.(message, channel)}
349
312
  />
350
- )}
351
- {!isMine && MessageActions && <MessageActions />}
352
- </div>
313
+ {MessageActions && <MessageActions />}
314
+ </div>
315
+ )}
353
316
  {message.text && (
354
317
  <div className="str-chat__message-bubble">
355
318
  <MessageText
@@ -359,6 +322,9 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
359
322
  </div>
360
323
  )}
361
324
  </div>
325
+ ) : isTipOnly ? (
326
+ /* Tip-only messages render as a standalone bubble */
327
+ <MessageTag message={message} standalone />
362
328
  ) : canRenderAttachmentsInToolkit ? (
363
329
  <div className="str-chat__message-bubble-wrapper">
364
330
  <div
@@ -5,7 +5,7 @@ import { QueryChannelAPIResponse, StreamChat } from 'stream-chat'
5
5
  import { Channel, Chat, type SendButtonProps } from 'stream-chat-react'
6
6
 
7
7
  import { createMockStreamChatClient } from '../../testing/createMockStreamChatClient'
8
- import LockedAttachment from '../CustomMessage/LockedAttachment'
8
+ import LockedAttachment from '../LockedAttachment'
9
9
 
10
10
  import { CustomMessageInput } from '.'
11
11
 
@@ -229,9 +229,7 @@ WithAttachments.parameters = {
229
229
  export const WithPaidAttachment: StoryFn<WrapperProps> = (args) => <Wrapper {...args} />
230
230
  WithPaidAttachment.args = {
231
231
  attachmentPreviewList: () => (
232
- <LockedAttachment
233
- isPreview
234
- contentType="media"
232
+ <LockedAttachment.Composer
235
233
  title="Exclusive Content"
236
234
  mimeType="image/jpeg"
237
235
  thumbnailUrl="https://picsum.photos/seed/paid/320/180"
@@ -268,7 +266,7 @@ WithPaidAttachment.parameters = {
268
266
  docs: {
269
267
  description: {
270
268
  story:
271
- "Message input with a paid attachment staged inside the input bubble. Uses `Channel`'s `AttachmentPreviewList` override to render a `LockedAttachment isPreview` card at the top of the input. `onDismiss` removes it; `onEditClick` reopens the paid content wizard.",
269
+ "Message input with a paid attachment staged inside the input bubble. Uses `Channel`'s `AttachmentPreviewList` override to render a `LockedAttachment.Composer` card at the top of the input. `onDismiss` removes it; `onEditClick` reopens the paid content wizard.",
272
270
  },
273
271
  },
274
272
  }