@linktr.ee/messaging-react 3.37.0-rc-1786190741 → 3.37.0

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 (91) hide show
  1. package/README.md +4 -4
  2. package/dist/Card-415OfRhw.cjs.map +1 -1
  3. package/dist/{Card-DVMzYquF.js → Card-D4PPD5qa.js} +8 -11
  4. package/dist/Card-D4PPD5qa.js.map +1 -0
  5. package/dist/Card-Dxk_Ggxw.cjs.map +1 -1
  6. package/dist/{Card-DaJtDL7m.js → Card-qS17qnN0.js} +6 -15
  7. package/dist/Card-qS17qnN0.js.map +1 -0
  8. package/dist/LoadingDots-Ct3WmVlT.js.map +1 -1
  9. package/dist/LoadingDots-D9GGphgM.cjs.map +1 -1
  10. package/dist/index-D7A8U8GQ.cjs.map +1 -1
  11. package/dist/{index-BOBIiAuD.js → index-DGmVyxHy.js} +62 -87
  12. package/dist/index-DGmVyxHy.js.map +1 -0
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +1 -1
  15. package/package.json +2 -2
  16. package/src/components/ActionButton/ActionButton.stories.tsx +2 -0
  17. package/src/components/ActionButton/ActionButton.test.tsx +55 -60
  18. package/src/components/ActionButton/index.tsx +14 -13
  19. package/src/components/AttachmentCard/AttachmentCard.stories.tsx +3 -1
  20. package/src/components/AttachmentCard/MediaPlayer.tsx +7 -9
  21. package/src/components/AttachmentCard/index.tsx +2 -6
  22. package/src/components/Avatar/Avatar.stories.tsx +5 -17
  23. package/src/components/Avatar/index.tsx +23 -13
  24. package/src/components/ChannelView.test.tsx +10 -6
  25. package/src/components/CustomMessage/CustomMessage.stories.tsx +2 -7
  26. package/src/components/CustomMessage/CustomMessage.test.tsx +3 -5
  27. package/src/components/CustomMessage/LockedAttachment/LockedAttachment.test.tsx +4 -5
  28. package/src/components/CustomMessage/LockedAttachment/components/Text/Card.tsx +4 -2
  29. package/src/components/CustomMessage/LockedAttachment/components/_shared/CardBody.tsx +6 -9
  30. package/src/components/CustomMessage/LockedAttachment/components/_shared/CardThumbnail.tsx +3 -1
  31. package/src/components/CustomMessage/LockedAttachment/components/_shared/GalleryThumbnail.tsx +4 -1
  32. package/src/components/CustomMessage/LockedAttachment/components/_shared/PurchaseStatusBadge.tsx +1 -0
  33. package/src/components/CustomMessage/LockedAttachment/components/_shared/SingleThumbnail.tsx +4 -1
  34. package/src/components/CustomMessage/LockedAttachment/components/_shared/SkeletonTextLines.tsx +2 -7
  35. package/src/components/CustomMessage/LockedAttachment/types.ts +3 -4
  36. package/src/components/CustomMessage/MessageAttachmentConversations.stories.tsx +86 -89
  37. package/src/components/CustomMessage/MessageVoteButtons.tsx +1 -4
  38. package/src/components/CustomMessage/SentMessageDeliveryStatus.test.tsx +10 -13
  39. package/src/components/CustomMessage/SentMessageDeliveryStatus.tsx +4 -1
  40. package/src/components/CustomMessage/StreamAttachmentMessage.stories.tsx +4 -4
  41. package/src/components/CustomMessage/StreamAttachmentMessage.test.tsx +7 -6
  42. package/src/components/CustomMessage/context.tsx +2 -7
  43. package/src/components/CustomMessage/index.tsx +4 -1
  44. package/src/components/CustomMessageInput/CustomMessageInput.stories.tsx +11 -33
  45. package/src/components/CustomMessageInput/CustomMessageInput.test.tsx +3 -3
  46. package/src/components/CustomSystemMessage/CustomSystemMessage.test.tsx +9 -6
  47. package/src/components/CustomTypingIndicator/CustomTypingIndicator.stories.tsx +1 -4
  48. package/src/components/IconButton/index.tsx +17 -21
  49. package/src/components/LinkAttachment/LinkAttachment.test.tsx +1 -4
  50. package/src/components/LinkAttachment/components/_shared/CardCta.tsx +1 -4
  51. package/src/components/Loading/Loading.stories.tsx +4 -1
  52. package/src/components/MediaMessage/MediaMessage.stories.tsx +18 -6
  53. package/src/components/MediaMessage/MediaMessage.test.tsx +16 -30
  54. package/src/components/MediaMessage/index.tsx +14 -51
  55. package/src/components/MessageAttachment/Audio/AudioAttachment.stories.tsx +2 -4
  56. package/src/components/MessageAttachment/File/FileAttachment.stories.tsx +1 -3
  57. package/src/components/MessageAttachment/Image/ImageAttachment.stories.tsx +4 -15
  58. package/src/components/MessageAttachment/Image/index.tsx +12 -6
  59. package/src/components/MessageAttachment/MessageAttachment.test.tsx +27 -59
  60. package/src/components/MessageAttachment/Pdf/PdfAttachment.stories.tsx +1 -3
  61. package/src/components/MessageAttachment/Pdf/index.tsx +3 -2
  62. package/src/components/MessageAttachment/Video/VideoAttachment.stories.tsx +3 -11
  63. package/src/components/MessageAttachment/Video/index.tsx +14 -9
  64. package/src/components/MessageAttachment/_shared/CompactDocumentRow.tsx +3 -1
  65. package/src/components/MessageAttachment/_shared/ImageViewer.tsx +3 -1
  66. package/src/components/MessageAttachment/_shared/MediaStackGrid.tsx +1 -5
  67. package/src/components/MessageAttachment/_shared/PdfViewer.tsx +3 -1
  68. package/src/components/MessageAttachment/_shared/VideoViewer.tsx +3 -1
  69. package/src/components/MessageAttachment/_shared/fileMeta.test.ts +6 -4
  70. package/src/components/MessageAttachment/stories/StoryTable.tsx +3 -1
  71. package/src/components/MessageBubble/MessageBubble.stories.tsx +1 -5
  72. package/src/components/MessageBubble/MessageBubble.test.tsx +3 -1
  73. package/src/components/MessageBubble/components/_shared/bubbleTail.tsx +1 -2
  74. package/src/components/MessagingShell/LoadingState.stories.tsx +1 -0
  75. package/src/components/RichCard/RichCard.stories.tsx +3 -14
  76. package/src/components/RichCard/RichCard.test.tsx +4 -16
  77. package/src/components/RichCard/RichCardBody.tsx +3 -11
  78. package/src/components/RichCard/RichCardCard.tsx +3 -1
  79. package/src/components/RichCard/RichCardImages.tsx +4 -2
  80. package/src/components/SearchInput/SearchInput.stories.tsx +1 -0
  81. package/src/components/SearchInput/SearchInput.test.tsx +65 -94
  82. package/src/hooks/useChannelStar.ts +1 -3
  83. package/src/hooks/useMessaging.ts +4 -4
  84. package/src/stories/decorators/storyUser.tsx +2 -2
  85. package/src/stories/mocks.tsx +1 -4
  86. package/src/styles.css +8 -23
  87. package/src/types.ts +2 -1
  88. package/src/utils/cdnImageUrl.test.ts +1 -3
  89. package/dist/Card-DVMzYquF.js.map +0 -1
  90. package/dist/Card-DaJtDL7m.js.map +0 -1
  91. package/dist/index-BOBIiAuD.js.map +0 -1
@@ -88,9 +88,7 @@ const ChatRow: React.FC<{
88
88
  ) : null}
89
89
  </div>
90
90
  ) : null}
91
- <div
92
- className={role === 'sender' ? 'flex justify-end' : 'flex justify-start'}
93
- >
91
+ <div className={role === 'sender' ? 'flex justify-end' : 'flex justify-start'}>
94
92
  {children}
95
93
  </div>
96
94
  </div>
@@ -605,92 +603,91 @@ ConversationWithFiles.parameters = skipInChromatic
605
603
  * and a PDF handoff. Useful for sanity-checking spacing and bubble
606
604
  * rhythm when multiple attachment types coexist.
607
605
  */
608
- export const ConversationWithMixedAttachments: StoryFn<
609
- ConversationStoryArgs
610
- > = ({ currentUser }) => {
611
- const isSenderTheCreator = currentUser.id === storyUsers.creator.id
612
- const receiver = isSenderTheCreator ? storyUsers.visitor : storyUsers.creator
613
- return (
614
- <ChatMock
615
- currentUser={currentUser}
616
- receiver={receiver}
617
- messages={[
618
- {
619
- id: 'msg-1',
620
- role: 'receiver',
621
- content: 'Hey! Got a sec to look at the launch package?',
622
- },
623
- {
624
- id: 'msg-2',
625
- role: 'sender',
626
- content: 'Yep, send it over.',
627
- },
628
- {
629
- id: 'msg-3',
630
- role: 'receiver',
631
- content: 'Here is the hero shot for the page',
632
- },
633
- {
634
- id: 'msg-4',
635
- role: 'receiver',
636
- content: (
637
- <MessageAttachment.Image.Received
638
- src={HERO_PHOTO}
639
- alt="Hero shot"
640
- filename="hero.jpg"
641
- />
642
- ),
643
- },
644
- {
645
- id: 'msg-5',
646
- role: 'receiver',
647
- content: (
648
- <MessageAttachment.Video.Received
649
- src={VIDEO_SRC}
650
- poster={VIDEO_POSTER}
651
- mimeType="video/mp4"
652
- filename="trailer.mp4"
653
- text="And the rough trailer ↑"
654
- />
655
- ),
656
- },
657
- {
658
- id: 'msg-6',
659
- role: 'sender',
660
- content: 'Looks great. Quick voice memo with notes ↓',
661
- },
662
- {
663
- id: 'msg-7',
664
- role: 'sender',
665
- content: (
666
- <MessageAttachment.Audio.Sent
667
- src={AUDIO_SRC}
668
- mimeType="audio/mpeg"
669
- filename="notes.mp3"
670
- />
671
- ),
672
- },
673
- {
674
- id: 'msg-8',
675
- role: 'sender',
676
- content: (
677
- <MessageAttachment.Pdf.Sent
678
- src={PDF_SRC}
679
- filename="launch-checklist.pdf"
680
- fileSize={142_336}
681
- text="And the launch checklist for the dry run."
682
- />
683
- ),
684
- },
685
- {
686
- id: 'msg-9',
687
- role: 'receiver',
688
- content: 'Got everything. Will sync back in the morning.',
689
- },
690
- ]}
691
- />
692
- )
693
- }
606
+ export const ConversationWithMixedAttachments: StoryFn<ConversationStoryArgs> =
607
+ ({ currentUser }) => {
608
+ const isSenderTheCreator = currentUser.id === storyUsers.creator.id
609
+ const receiver = isSenderTheCreator ? storyUsers.visitor : storyUsers.creator
610
+ return (
611
+ <ChatMock
612
+ currentUser={currentUser}
613
+ receiver={receiver}
614
+ messages={[
615
+ {
616
+ id: 'msg-1',
617
+ role: 'receiver',
618
+ content: 'Hey! Got a sec to look at the launch package?',
619
+ },
620
+ {
621
+ id: 'msg-2',
622
+ role: 'sender',
623
+ content: 'Yep, send it over.',
624
+ },
625
+ {
626
+ id: 'msg-3',
627
+ role: 'receiver',
628
+ content: 'Here is the hero shot for the page',
629
+ },
630
+ {
631
+ id: 'msg-4',
632
+ role: 'receiver',
633
+ content: (
634
+ <MessageAttachment.Image.Received
635
+ src={HERO_PHOTO}
636
+ alt="Hero shot"
637
+ filename="hero.jpg"
638
+ />
639
+ ),
640
+ },
641
+ {
642
+ id: 'msg-5',
643
+ role: 'receiver',
644
+ content: (
645
+ <MessageAttachment.Video.Received
646
+ src={VIDEO_SRC}
647
+ poster={VIDEO_POSTER}
648
+ mimeType="video/mp4"
649
+ filename="trailer.mp4"
650
+ text="And the rough trailer"
651
+ />
652
+ ),
653
+ },
654
+ {
655
+ id: 'msg-6',
656
+ role: 'sender',
657
+ content: 'Looks great. Quick voice memo with notes ↓',
658
+ },
659
+ {
660
+ id: 'msg-7',
661
+ role: 'sender',
662
+ content: (
663
+ <MessageAttachment.Audio.Sent
664
+ src={AUDIO_SRC}
665
+ mimeType="audio/mpeg"
666
+ filename="notes.mp3"
667
+ />
668
+ ),
669
+ },
670
+ {
671
+ id: 'msg-8',
672
+ role: 'sender',
673
+ content: (
674
+ <MessageAttachment.Pdf.Sent
675
+ src={PDF_SRC}
676
+ filename="launch-checklist.pdf"
677
+ fileSize={142_336}
678
+ text="And the launch checklist for the dry run."
679
+ />
680
+ ),
681
+ },
682
+ {
683
+ id: 'msg-9',
684
+ role: 'receiver',
685
+ content: 'Got everything. Will sync back in the morning.',
686
+ },
687
+ ]}
688
+ />
689
+ )
690
+ }
694
691
 
695
692
  /**
696
693
  * Multi-attachment message — audio + PDF.
@@ -38,10 +38,7 @@ export const MessageVoteButtons: React.FC<MessageVoteButtonsProps> = ({
38
38
  aria-pressed={selected === 'down'}
39
39
  data-tooltip="Bad response"
40
40
  >
41
- <ThumbsDownIcon
42
- size={16}
43
- weight={selected === 'down' ? 'fill' : 'regular'}
44
- />
41
+ <ThumbsDownIcon size={16} weight={selected === 'down' ? 'fill' : 'regular'} />
45
42
  </button>
46
43
  </div>
47
44
  )
@@ -260,9 +260,10 @@ describe('SentMessageDeliveryStatus', () => {
260
260
  expect(screen.getAllByText('•')).toHaveLength(1)
261
261
  expect(button).not.toHaveTextContent('•')
262
262
  expect(name).toHaveClass('sent-message-broadcast-name')
263
- expect(
264
- button.querySelector('.sent-message-broadcast-badge')
265
- ).toHaveAttribute('aria-hidden', 'true')
263
+ expect(button.querySelector('.sent-message-broadcast-badge')).toHaveAttribute(
264
+ 'aria-hidden',
265
+ 'true'
266
+ )
266
267
  expect(screen.getAllByTestId('sent-message-delivery-status')).toHaveLength(
267
268
  3
268
269
  )
@@ -289,11 +290,9 @@ describe('SentMessageDeliveryStatus', () => {
289
290
  />
290
291
  )
291
292
 
292
- screen
293
- .getByRole('button', {
294
- name: 'View broadcast July 9th Class absentee',
295
- })
296
- .click()
293
+ screen.getByRole('button', {
294
+ name: 'View broadcast July 9th Class absentee',
295
+ }).click()
297
296
 
298
297
  expect(onBroadcastClick).toHaveBeenCalledWith({
299
298
  id: 'broadcast-1',
@@ -322,11 +321,9 @@ describe('SentMessageDeliveryStatus', () => {
322
321
  />
323
322
  )
324
323
 
325
- screen
326
- .getByRole('button', {
327
- name: 'View broadcast Broadcast',
328
- })
329
- .click()
324
+ screen.getByRole('button', {
325
+ name: 'View broadcast Broadcast',
326
+ }).click()
330
327
 
331
328
  expect(onBroadcastClick).toHaveBeenCalledWith({
332
329
  id: 'broadcast-1',
@@ -219,7 +219,10 @@ export const SentMessageDeliveryStatus = ({
219
219
  <span className="sent-message-status-row">
220
220
  {messageStatus}
221
221
  {isLatestRealMessage && (
222
- <span className="sent-message-broadcast-separator" aria-hidden="true">
222
+ <span
223
+ className="sent-message-broadcast-separator"
224
+ aria-hidden="true"
225
+ >
223
226
 
224
227
  </span>
225
228
  )}
@@ -28,10 +28,10 @@ import StreamAttachmentMessage from './StreamAttachmentMessage'
28
28
  * ancestry that Stream bubble chrome and the MES-1031 tails are scoped under.
29
29
  * ────────────────────────────────────────────────────────────────── */
30
30
 
31
- const Bubbles: React.FC<{
32
- isMyMessage: boolean
33
- children: React.ReactNode
34
- }> = ({ isMyMessage, children }) => (
31
+ const Bubbles: React.FC<{ isMyMessage: boolean; children: React.ReactNode }> = ({
32
+ isMyMessage,
33
+ children,
34
+ }) => (
35
35
  <div className="str-chat mx-auto max-w-2xl p-12">
36
36
  {/* Tail CSS is scoped to `.str-chat__li--single|--bottom`; bubble surface
37
37
  styles need `.str-chat__message--me|other`. */}
@@ -9,8 +9,10 @@ import StreamAttachmentMessage, {
9
9
  linkCardPropsFromStreamAttachment,
10
10
  } from './StreamAttachmentMessage'
11
11
 
12
- const message = (attachments: Attachment[], text?: string): LocalMessage =>
13
- ({ attachments, text }) as LocalMessage
12
+ const message = (
13
+ attachments: Attachment[],
14
+ text?: string
15
+ ): LocalMessage => ({ attachments, text }) as LocalMessage
14
16
 
15
17
  describe('linkCardPropsFromStreamAttachment', () => {
16
18
  it('uses the featured layout when a thumbnail is present', () => {
@@ -97,10 +99,9 @@ describe('StreamAttachmentMessage', () => {
97
99
  />
98
100
  )
99
101
 
100
- expect(screen.getByRole('link', { name: /my linktree/i })).toHaveAttribute(
101
- 'href',
102
- 'https://linktr.ee/someone'
103
- )
102
+ expect(
103
+ screen.getByRole('link', { name: /my linktree/i })
104
+ ).toHaveAttribute('href', 'https://linktr.ee/someone')
104
105
  expect(screen.queryByText('https://linktr.ee/someone !')).toBeNull()
105
106
  })
106
107
 
@@ -1,9 +1,6 @@
1
1
  import { createContext, useContext } from 'react'
2
2
 
3
- import {
4
- defaultLockedAttachmentContextValue,
5
- type LockedAttachmentContextValue,
6
- } from './LockedAttachment/types'
3
+ import { defaultLockedAttachmentContextValue, type LockedAttachmentContextValue } from './LockedAttachment/types'
7
4
 
8
5
  export interface CustomMessageRegistry {
9
6
  LockedAttachment: LockedAttachmentContextValue
@@ -17,9 +14,7 @@ const CustomMessageContext = createContext<Partial<CustomMessageRegistry>>({})
17
14
 
18
15
  export const CustomMessageProvider = CustomMessageContext.Provider
19
16
 
20
- export function useCustomMessage<K extends keyof CustomMessageRegistry>(
21
- key: K
22
- ): CustomMessageRegistry[K] {
17
+ export function useCustomMessage<K extends keyof CustomMessageRegistry>(key: K): CustomMessageRegistry[K] {
23
18
  const ctx = useContext(CustomMessageContext)
24
19
  return (ctx[key] ?? customMessageDefaults[key]) as CustomMessageRegistry[K]
25
20
  }
@@ -307,7 +307,10 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
307
307
  <div className="flex items-center gap-2">
308
308
  {isMine && MessageActions && <MessageActions />}
309
309
  {isMine ? (
310
- <LockedAttachment {...sharedLockedTextProps} isMine={true} />
310
+ <LockedAttachment
311
+ {...sharedLockedTextProps}
312
+ isMine={true}
313
+ />
311
314
  ) : (
312
315
  <LockedAttachment
313
316
  {...sharedLockedTextProps}
@@ -85,20 +85,11 @@ type WrapperProps = {
85
85
  }
86
86
 
87
87
  const Wrapper: React.FC<WrapperProps> = (props) => {
88
- const {
89
- frozen,
90
- renderActions,
91
- sendButton,
92
- attachmentPreviewList,
93
- renderFooter,
94
- surfaceHeight,
95
- } = props
88
+ const { frozen, renderActions, sendButton, attachmentPreviewList, renderFooter, surfaceHeight } = props
96
89
 
97
90
  const [client] = React.useState(() => createMockStreamChatClient(mockUser))
98
91
 
99
- const [channel, setChannel] = React.useState<ReturnType<
100
- StreamChat['channel']
101
- > | null>(null)
92
+ const [channel, setChannel] = React.useState<ReturnType<StreamChat['channel']> | null>(null)
102
93
 
103
94
  useEffect(() => {
104
95
  createMockChannel(client, { frozen }).then(setChannel)
@@ -111,9 +102,7 @@ const Wrapper: React.FC<WrapperProps> = (props) => {
111
102
  <Channel
112
103
  channel={channel}
113
104
  {...(sendButton ? { SendButton: sendButton } : {})}
114
- {...(attachmentPreviewList
115
- ? { AttachmentPreviewList: attachmentPreviewList }
116
- : {})}
105
+ {...(attachmentPreviewList ? { AttachmentPreviewList: attachmentPreviewList } : {})}
117
106
  >
118
107
  <div
119
108
  className="bg-white"
@@ -132,10 +121,7 @@ const Wrapper: React.FC<WrapperProps> = (props) => {
132
121
  } as React.CSSProperties
133
122
  }
134
123
  >
135
- <CustomMessageInput
136
- renderActions={renderActions}
137
- renderFooter={renderFooter}
138
- />
124
+ <CustomMessageInput renderActions={renderActions} renderFooter={renderFooter} />
139
125
  </div>
140
126
  </Channel>
141
127
  </Chat>
@@ -181,9 +167,7 @@ Frozen.parameters = {
181
167
  },
182
168
  }
183
169
 
184
- export const WithCustomActionButton: StoryFn<WrapperProps> = (args) => (
185
- <Wrapper {...args} />
186
- )
170
+ export const WithCustomActionButton: StoryFn<WrapperProps> = (args) => <Wrapper {...args} />
187
171
  WithCustomActionButton.args = {
188
172
  renderActions: () => (
189
173
  <button
@@ -223,9 +207,7 @@ const PurpleMediaSendButton: React.FC<SendButtonProps> = (props) => {
223
207
  )
224
208
  }
225
209
 
226
- export const WithCustomSendButton: StoryFn<WrapperProps> = (args) => (
227
- <Wrapper {...args} />
228
- )
210
+ export const WithCustomSendButton: StoryFn<WrapperProps> = (args) => <Wrapper {...args} />
229
211
  WithCustomSendButton.args = { sendButton: PurpleMediaSendButton }
230
212
  WithCustomSendButton.parameters = {
231
213
  docs: {
@@ -236,9 +218,7 @@ WithCustomSendButton.parameters = {
236
218
  },
237
219
  }
238
220
 
239
- export const WithAttachments: StoryFn<WrapperProps> = (args) => (
240
- <Wrapper {...args} />
241
- )
221
+ export const WithAttachments: StoryFn<WrapperProps> = (args) => <Wrapper {...args} />
242
222
  WithAttachments.args = {
243
223
  attachmentPreviewList: () => (
244
224
  <div className="relative size-20 shrink-0 overflow-hidden rounded-2xl border border-black/8">
@@ -269,9 +249,9 @@ WithAttachments.parameters = {
269
249
  },
270
250
  }
271
251
 
272
- export const WithStagedLinkPreviewUnderKeyboard: StoryFn<WrapperProps> = (
273
- args
274
- ) => <Wrapper {...args} />
252
+ export const WithStagedLinkPreviewUnderKeyboard: StoryFn<WrapperProps> = (args) => (
253
+ <Wrapper {...args} />
254
+ )
275
255
  WithStagedLinkPreviewUnderKeyboard.args = {
276
256
  // Roughly a 393x852 phone with the soft keyboard up, so the 250px staged card
277
257
  // alone outgrows the composer's cap (half of this) and the card scrolls.
@@ -294,9 +274,7 @@ WithStagedLinkPreviewUnderKeyboard.parameters = {
294
274
  },
295
275
  }
296
276
 
297
- export const WithPaidAttachment: StoryFn<WrapperProps> = (args) => (
298
- <Wrapper {...args} />
299
- )
277
+ export const WithPaidAttachment: StoryFn<WrapperProps> = (args) => <Wrapper {...args} />
300
278
  WithPaidAttachment.args = {
301
279
  attachmentPreviewList: () => (
302
280
  <LockedAttachment
@@ -375,9 +375,9 @@ describe('CustomMessageInput', () => {
375
375
  // Nothing inside may shrink, or the previews get cropped to make room for
376
376
  // the textarea instead of scrolling with it.
377
377
  expect(card).not.toHaveClass('min-h-0')
378
- expect(
379
- card.querySelector('.messaging-composer-previews')
380
- ).not.toHaveClass('min-h-0')
378
+ expect(card.querySelector('.messaging-composer-previews')).not.toHaveClass(
379
+ 'min-h-0'
380
+ )
381
381
  expect(card.querySelector('.messaging-composer-row')).not.toHaveClass(
382
382
  'shrink-0'
383
383
  )
@@ -51,13 +51,16 @@ describe('CustomSystemMessage', () => {
51
51
  it.each([
52
52
  { metadata: {}, text: 'Unknown system message' },
53
53
  { text: 'Absent system type' },
54
- ])('hides the timestamp for unknown or absent system types', (overrides) => {
55
- const { container } = renderWithProviders(
56
- <CustomSystemMessage {...createProps(overrides)} />
57
- )
54
+ ])(
55
+ 'hides the timestamp for unknown or absent system types',
56
+ (overrides) => {
57
+ const { container } = renderWithProviders(
58
+ <CustomSystemMessage {...createProps(overrides)} />
59
+ )
58
60
 
59
- expect(container.querySelector('time')).not.toBeInTheDocument()
60
- })
61
+ expect(container.querySelector('time')).not.toBeInTheDocument()
62
+ }
63
+ )
61
64
 
62
65
  it('hides the timestamp for legacy dm-agent messages without a custom_type', () => {
63
66
  const { container } = renderWithProviders(
@@ -38,10 +38,7 @@ const defaultTyping: Record<string, Event> = {
38
38
  } as Event,
39
39
  }
40
40
 
41
- type ListenerMap = Record<
42
- string,
43
- (event: { ai_state: string; cid: string }) => void
44
- >
41
+ type ListenerMap = Record<string, (event: { ai_state: string; cid: string }) => void>
45
42
 
46
43
  const createMockChannel = ({ aiState }: { aiState?: string }) => {
47
44
  const listeners: ListenerMap = {}
@@ -1,36 +1,32 @@
1
- import classNames from 'classnames'
2
- import React from 'react'
1
+ import classNames from "classnames";
2
+ import React from "react";
3
3
 
4
- interface IconButtonProps extends Omit<
5
- React.ButtonHTMLAttributes<HTMLButtonElement>,
6
- 'type' | 'children'
7
- > {
8
- label: string
9
- children: React.ReactNode
10
- className?: string
4
+ interface IconButtonProps
5
+ extends Omit<
6
+ React.ButtonHTMLAttributes<HTMLButtonElement>,
7
+ "type" | "children"
8
+ > {
9
+ label: string;
10
+ children: React.ReactNode;
11
+ className?: string;
11
12
  }
12
13
 
13
- export function IconButton({
14
- label,
15
- className,
16
- children,
17
- ...rest
18
- }: IconButtonProps) {
14
+ export function IconButton({ label, className, children, ...rest }: IconButtonProps) {
19
15
  return (
20
16
  <button
21
17
  type="button"
22
18
  className={classNames(
23
- 'inline-flex items-center justify-center rounded-full transition-colors focus-ring p-2',
19
+ "inline-flex items-center justify-center rounded-full transition-colors focus-ring p-2",
24
20
  {
25
- 'cursor-not-allowed opacity-50': rest.disabled,
26
- 'hover:bg-sand': !rest.disabled,
21
+ "cursor-not-allowed opacity-50": rest.disabled,
22
+ "hover:bg-sand": !rest.disabled,
27
23
  },
28
- className
24
+ className,
29
25
  )}
30
26
  {...rest}
31
27
  >
32
28
  <span className="sr-only">{label}</span>
33
29
  {children}
34
30
  </button>
35
- )
36
- }
31
+ );
32
+ }
@@ -60,10 +60,7 @@ describe('LinkAttachment.Received (link previews)', () => {
60
60
 
61
61
  it('truncates the description to a single line by default', async () => {
62
62
  renderWithProviders(
63
- <LinkAttachment.Received
64
- title="Official"
65
- description="A longer body of prose that would wrap onto several lines"
66
- />
63
+ <LinkAttachment.Received title="Official" description="A longer body of prose that would wrap onto several lines" />
67
64
  )
68
65
  const description = await screen.findByText(
69
66
  'A longer body of prose that would wrap onto several lines'
@@ -32,10 +32,7 @@ type CtaEmphasis = NonNullable<LinkAttachmentCta['variant']>
32
32
  // component-library preset has no neutral button token (`primary` is brand
33
33
  // purple), and the host preset can't retheme arbitrary hex. Align the grey with
34
34
  // the Arbor secondary token when the shared design tokens land.
35
- const BUTTON_CLASS_BY_VARIANT: Record<
36
- LinkAttachmentVariant,
37
- Record<CtaEmphasis, string>
38
- > = {
35
+ const BUTTON_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, Record<CtaEmphasis, string>> = {
39
36
  dark: {
40
37
  primary: 'bg-white text-[#121110] hover:bg-white/90',
41
38
  secondary: 'bg-white/15 text-white hover:bg-white/25',
@@ -15,8 +15,11 @@ const meta: Meta<ComponentProps> = {
15
15
  export default meta
16
16
 
17
17
  const Template: StoryFn<ComponentProps> = (args) => {
18
- return <Loading {...args} className="w-10 h-10" />
18
+ return (
19
+ <Loading {...args} className='w-10 h-10' />
20
+ )
19
21
  }
20
22
 
21
23
  export const Default: StoryFn<ComponentProps> = Template.bind({})
22
24
  Default.args = {}
25
+
@@ -169,7 +169,9 @@ export const Attachment: StoryFn = () => (
169
169
  <MediaMessage
170
170
  isMyMessage={false}
171
171
  message={base({
172
- attachments: [attachment as MessageAttachment],
172
+ attachments: [
173
+ attachment as MessageAttachment,
174
+ ],
173
175
  })}
174
176
  />
175
177
  </td>
@@ -184,7 +186,9 @@ export const Attachment: StoryFn = () => (
184
186
  <MediaMessage
185
187
  isMyMessage={true}
186
188
  message={base({
187
- attachments: [attachment as MessageAttachment],
189
+ attachments: [
190
+ attachment as MessageAttachment,
191
+ ],
188
192
  })}
189
193
  />
190
194
  </td>
@@ -207,7 +211,9 @@ export const Links: StoryFn = () => (
207
211
  <MediaMessage
208
212
  isMyMessage={false}
209
213
  message={base({
210
- attachments: [attachment as MessageAttachment],
214
+ attachments: [
215
+ attachment as MessageAttachment,
216
+ ],
211
217
  })}
212
218
  />
213
219
  </td>
@@ -222,7 +228,9 @@ export const Links: StoryFn = () => (
222
228
  <MediaMessage
223
229
  isMyMessage={true}
224
230
  message={base({
225
- attachments: [attachment as MessageAttachment],
231
+ attachments: [
232
+ attachment as MessageAttachment,
233
+ ],
226
234
  })}
227
235
  />
228
236
  </td>
@@ -245,7 +253,9 @@ export const Compound: StoryFn = () => (
245
253
  <td key={label} className="align-top">
246
254
  <MediaMessage.Visitor
247
255
  message={base({
248
- attachments: [attachment as MessageAttachment],
256
+ attachments: [
257
+ attachment as MessageAttachment,
258
+ ],
249
259
  })}
250
260
  />
251
261
  </td>
@@ -259,7 +269,9 @@ export const Compound: StoryFn = () => (
259
269
  <td key={label} className="align-top">
260
270
  <MediaMessage.Creator
261
271
  message={base({
262
- attachments: [attachment as MessageAttachment],
272
+ attachments: [
273
+ attachment as MessageAttachment,
274
+ ],
263
275
  })}
264
276
  />
265
277
  </td>