@linktr.ee/messaging-react 3.37.0 → 3.37.1

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-D4PPD5qa.js → Card-DVMzYquF.js} +11 -8
  4. package/dist/Card-DVMzYquF.js.map +1 -0
  5. package/dist/{Card-qS17qnN0.js → Card-DaJtDL7m.js} +15 -6
  6. package/dist/Card-DaJtDL7m.js.map +1 -0
  7. package/dist/Card-Dxk_Ggxw.cjs.map +1 -1
  8. package/dist/LoadingDots-Ct3WmVlT.js.map +1 -1
  9. package/dist/LoadingDots-D9GGphgM.cjs.map +1 -1
  10. package/dist/{index-DGmVyxHy.js → index-BOBIiAuD.js} +87 -62
  11. package/dist/index-BOBIiAuD.js.map +1 -0
  12. package/dist/index-D7A8U8GQ.cjs.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +1 -1
  15. package/package.json +3 -2
  16. package/src/components/ActionButton/ActionButton.stories.tsx +0 -2
  17. package/src/components/ActionButton/ActionButton.test.tsx +60 -55
  18. package/src/components/ActionButton/index.tsx +13 -14
  19. package/src/components/AttachmentCard/AttachmentCard.stories.tsx +1 -3
  20. package/src/components/AttachmentCard/MediaPlayer.tsx +9 -7
  21. package/src/components/AttachmentCard/index.tsx +6 -2
  22. package/src/components/Avatar/Avatar.stories.tsx +17 -5
  23. package/src/components/Avatar/index.tsx +13 -23
  24. package/src/components/ChannelView.test.tsx +6 -10
  25. package/src/components/CustomMessage/CustomMessage.stories.tsx +7 -2
  26. package/src/components/CustomMessage/CustomMessage.test.tsx +5 -3
  27. package/src/components/CustomMessage/LockedAttachment/LockedAttachment.test.tsx +5 -4
  28. package/src/components/CustomMessage/LockedAttachment/components/Text/Card.tsx +2 -4
  29. package/src/components/CustomMessage/LockedAttachment/components/_shared/CardBody.tsx +9 -6
  30. package/src/components/CustomMessage/LockedAttachment/components/_shared/CardThumbnail.tsx +1 -3
  31. package/src/components/CustomMessage/LockedAttachment/components/_shared/GalleryThumbnail.tsx +1 -4
  32. package/src/components/CustomMessage/LockedAttachment/components/_shared/PurchaseStatusBadge.tsx +0 -1
  33. package/src/components/CustomMessage/LockedAttachment/components/_shared/SingleThumbnail.tsx +1 -4
  34. package/src/components/CustomMessage/LockedAttachment/components/_shared/SkeletonTextLines.tsx +7 -2
  35. package/src/components/CustomMessage/LockedAttachment/types.ts +4 -3
  36. package/src/components/CustomMessage/MessageAttachmentConversations.stories.tsx +89 -86
  37. package/src/components/CustomMessage/MessageVoteButtons.tsx +4 -1
  38. package/src/components/CustomMessage/SentMessageDeliveryStatus.test.tsx +13 -10
  39. package/src/components/CustomMessage/SentMessageDeliveryStatus.tsx +1 -4
  40. package/src/components/CustomMessage/StreamAttachmentMessage.stories.tsx +4 -4
  41. package/src/components/CustomMessage/StreamAttachmentMessage.test.tsx +6 -7
  42. package/src/components/CustomMessage/context.tsx +7 -2
  43. package/src/components/CustomMessage/index.tsx +1 -4
  44. package/src/components/CustomMessageInput/CustomMessageInput.stories.tsx +33 -11
  45. package/src/components/CustomMessageInput/CustomMessageInput.test.tsx +3 -3
  46. package/src/components/CustomSystemMessage/CustomSystemMessage.test.tsx +6 -9
  47. package/src/components/CustomTypingIndicator/CustomTypingIndicator.stories.tsx +4 -1
  48. package/src/components/IconButton/index.tsx +21 -17
  49. package/src/components/LinkAttachment/LinkAttachment.test.tsx +4 -1
  50. package/src/components/LinkAttachment/components/_shared/CardCta.tsx +4 -1
  51. package/src/components/Loading/Loading.stories.tsx +1 -4
  52. package/src/components/MediaMessage/MediaMessage.stories.tsx +6 -18
  53. package/src/components/MediaMessage/MediaMessage.test.tsx +30 -16
  54. package/src/components/MediaMessage/index.tsx +51 -14
  55. package/src/components/MessageAttachment/Audio/AudioAttachment.stories.tsx +4 -2
  56. package/src/components/MessageAttachment/File/FileAttachment.stories.tsx +3 -1
  57. package/src/components/MessageAttachment/Image/ImageAttachment.stories.tsx +15 -4
  58. package/src/components/MessageAttachment/Image/index.tsx +6 -12
  59. package/src/components/MessageAttachment/MessageAttachment.test.tsx +59 -27
  60. package/src/components/MessageAttachment/Pdf/PdfAttachment.stories.tsx +3 -1
  61. package/src/components/MessageAttachment/Pdf/index.tsx +2 -3
  62. package/src/components/MessageAttachment/Video/VideoAttachment.stories.tsx +11 -3
  63. package/src/components/MessageAttachment/Video/index.tsx +9 -14
  64. package/src/components/MessageAttachment/_shared/CompactDocumentRow.tsx +1 -3
  65. package/src/components/MessageAttachment/_shared/ImageViewer.tsx +1 -3
  66. package/src/components/MessageAttachment/_shared/MediaStackGrid.tsx +5 -1
  67. package/src/components/MessageAttachment/_shared/PdfViewer.tsx +1 -3
  68. package/src/components/MessageAttachment/_shared/VideoViewer.tsx +1 -3
  69. package/src/components/MessageAttachment/_shared/fileMeta.test.ts +4 -6
  70. package/src/components/MessageAttachment/stories/StoryTable.tsx +1 -3
  71. package/src/components/MessageBubble/MessageBubble.stories.tsx +5 -1
  72. package/src/components/MessageBubble/MessageBubble.test.tsx +1 -3
  73. package/src/components/MessageBubble/components/_shared/bubbleTail.tsx +2 -1
  74. package/src/components/MessagingShell/LoadingState.stories.tsx +0 -1
  75. package/src/components/RichCard/RichCard.stories.tsx +14 -3
  76. package/src/components/RichCard/RichCard.test.tsx +16 -4
  77. package/src/components/RichCard/RichCardBody.tsx +11 -3
  78. package/src/components/RichCard/RichCardCard.tsx +1 -3
  79. package/src/components/RichCard/RichCardImages.tsx +2 -4
  80. package/src/components/SearchInput/SearchInput.stories.tsx +0 -1
  81. package/src/components/SearchInput/SearchInput.test.tsx +94 -65
  82. package/src/hooks/useChannelStar.ts +3 -1
  83. package/src/hooks/useMessaging.ts +4 -4
  84. package/src/stories/decorators/storyUser.tsx +2 -2
  85. package/src/stories/mocks.tsx +4 -1
  86. package/src/styles.css +23 -8
  87. package/src/types.ts +1 -2
  88. package/src/utils/cdnImageUrl.test.ts +3 -1
  89. package/dist/Card-D4PPD5qa.js.map +0 -1
  90. package/dist/Card-qS17qnN0.js.map +0 -1
  91. package/dist/index-DGmVyxHy.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -28,7 +28,7 @@ import { StreamChatServiceConfig } from '@linktr.ee/messaging-core';
28
28
  export declare const ActionButton: ({ variant, className, children, ...rest }: ActionButtonProps) => JSX_2.Element;
29
29
 
30
30
  export declare interface ActionButtonProps extends default_2.ButtonHTMLAttributes<HTMLButtonElement> {
31
- variant?: "default" | "danger";
31
+ variant?: 'default' | 'danger';
32
32
  }
33
33
 
34
34
  export declare type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document';
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 h, k as L, l as d, m as p, R 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, x as y, o as z, y as B, z as S, B as q, D, E, G as R, H as V, I as w } from "./index-DGmVyxHy.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 h, k as L, l as d, m as p, R 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, x as y, o as z, y as B, z as S, B as q, D, E, G as R, H as V, I as w } from "./index-BOBIiAuD.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.37.0",
3
+ "version": "3.37.1",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -49,12 +49,13 @@
49
49
  "chromatic:ci:main": "chromatic --ci --auto-accept-changes"
50
50
  },
51
51
  "dependencies": {
52
- "@linktr.ee/component-library": "11.8.6",
53
52
  "@linktr.ee/messaging-core": "^2.4.0",
54
53
  "@linktr.ee/messaging-taxonomy": "^0.9.0",
55
54
  "@phosphor-icons/react": "^2.1.10"
56
55
  },
57
56
  "devDependencies": {
57
+ "@linktr.ee/arbor": "25.0.0",
58
+ "@linktr.ee/design-tokens": "14.0.0",
58
59
  "@storybook/addon-essentials": "^8.5.0",
59
60
  "@storybook/addon-interactions": "^8.5.0",
60
61
  "@storybook/addon-links": "^8.5.0",
@@ -3,7 +3,6 @@ import React from 'react'
3
3
 
4
4
  import ActionButton from '.'
5
5
 
6
-
7
6
  type ComponentProps = React.ComponentProps<typeof ActionButton>
8
7
 
9
8
  const meta: Meta<ComponentProps> = {
@@ -44,4 +43,3 @@ Disabled.args = {
44
43
  variant: 'default',
45
44
  disabled: true,
46
45
  }
47
-
@@ -1,89 +1,94 @@
1
- import { describe, it, expect, vi } from 'vitest';
1
+ import { describe, it, expect, vi } from 'vitest'
2
2
 
3
- import { renderWithProviders, screen, userEvent } from '../../test/utils';
3
+ import { renderWithProviders, screen, userEvent } from '../../test/utils'
4
4
 
5
- import ActionButton from '.';
5
+ import ActionButton from '.'
6
6
 
7
7
  describe('ActionButton', () => {
8
8
  describe('Rendering', () => {
9
9
  it('renders with children text', () => {
10
- renderWithProviders(<ActionButton>Click me</ActionButton>);
11
- expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
12
- });
13
- });
10
+ renderWithProviders(<ActionButton>Click me</ActionButton>)
11
+ expect(
12
+ screen.getByRole('button', { name: 'Click me' })
13
+ ).toBeInTheDocument()
14
+ })
15
+ })
14
16
 
15
17
  describe('Disabled State', () => {
16
18
  it('is disabled when disabled prop is true', () => {
17
- renderWithProviders(<ActionButton disabled>Disabled</ActionButton>);
18
- const button = screen.getByRole('button');
19
- expect(button).toBeDisabled();
20
- });
19
+ renderWithProviders(<ActionButton disabled>Disabled</ActionButton>)
20
+ const button = screen.getByRole('button')
21
+ expect(button).toBeDisabled()
22
+ })
21
23
 
22
24
  it('does not trigger onClick when disabled', async () => {
23
- const handleClick = vi.fn();
24
- const user = userEvent.setup();
25
-
25
+ const handleClick = vi.fn()
26
+ const user = userEvent.setup()
27
+
26
28
  renderWithProviders(
27
29
  <ActionButton disabled onClick={handleClick}>
28
30
  Disabled
29
31
  </ActionButton>
30
- );
32
+ )
31
33
 
32
- const button = screen.getByRole('button');
33
- await user.click(button);
34
+ const button = screen.getByRole('button')
35
+ await user.click(button)
34
36
 
35
- expect(handleClick).not.toHaveBeenCalled();
36
- });
37
- });
37
+ expect(handleClick).not.toHaveBeenCalled()
38
+ })
39
+ })
38
40
 
39
41
  describe('Click Handling', () => {
40
42
  it('calls onClick when clicked', async () => {
41
- const handleClick = vi.fn();
42
- const user = userEvent.setup();
43
-
44
- renderWithProviders(<ActionButton onClick={handleClick}>Click me</ActionButton>);
43
+ const handleClick = vi.fn()
44
+ const user = userEvent.setup()
45
+
46
+ renderWithProviders(
47
+ <ActionButton onClick={handleClick}>Click me</ActionButton>
48
+ )
45
49
 
46
- const button = screen.getByRole('button');
47
- await user.click(button);
50
+ const button = screen.getByRole('button')
51
+ await user.click(button)
48
52
 
49
- expect(handleClick).toHaveBeenCalledTimes(1);
50
- });
51
- });
53
+ expect(handleClick).toHaveBeenCalledTimes(1)
54
+ })
55
+ })
52
56
 
53
57
  describe('Type Attribute', () => {
54
58
  it('has button type by default', () => {
55
- renderWithProviders(<ActionButton>Default Type</ActionButton>);
56
- const button = screen.getByRole('button');
57
- expect(button).toHaveAttribute('type', 'button');
58
- });
59
+ renderWithProviders(<ActionButton>Default Type</ActionButton>)
60
+ const button = screen.getByRole('button')
61
+ expect(button).toHaveAttribute('type', 'button')
62
+ })
59
63
 
60
64
  it('can have submit type', () => {
61
- renderWithProviders(<ActionButton type="submit">Submit</ActionButton>);
62
- const button = screen.getByRole('button');
63
- expect(button).toHaveAttribute('type', 'submit');
64
- });
65
- });
65
+ renderWithProviders(<ActionButton type="submit">Submit</ActionButton>)
66
+ const button = screen.getByRole('button')
67
+ expect(button).toHaveAttribute('type', 'submit')
68
+ })
69
+ })
66
70
 
67
71
  describe('Accessibility', () => {
68
72
  it('is keyboard accessible', async () => {
69
- const handleClick = vi.fn();
70
- const user = userEvent.setup();
71
-
72
- renderWithProviders(<ActionButton onClick={handleClick}>Press me</ActionButton>);
73
+ const handleClick = vi.fn()
74
+ const user = userEvent.setup()
73
75
 
74
- const button = screen.getByRole('button');
75
- button.focus();
76
- await user.keyboard('{Enter}');
76
+ renderWithProviders(
77
+ <ActionButton onClick={handleClick}>Press me</ActionButton>
78
+ )
77
79
 
78
- expect(handleClick).toHaveBeenCalledTimes(1);
79
- });
80
+ const button = screen.getByRole('button')
81
+ button.focus()
82
+ await user.keyboard('{Enter}')
80
83
 
81
- it('can be focused', () => {
82
- renderWithProviders(<ActionButton>Focus me</ActionButton>);
83
- const button = screen.getByRole('button');
84
- button.focus();
85
- expect(button).toHaveFocus();
86
- });
87
- });
88
- });
84
+ expect(handleClick).toHaveBeenCalledTimes(1)
85
+ })
89
86
 
87
+ it('can be focused', () => {
88
+ renderWithProviders(<ActionButton>Focus me</ActionButton>)
89
+ const button = screen.getByRole('button')
90
+ button.focus()
91
+ expect(button).toHaveFocus()
92
+ })
93
+ })
94
+ })
@@ -1,33 +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
- export interface ActionButtonProps
5
- extends React.ButtonHTMLAttributes<HTMLButtonElement> {
6
- variant?: "default" | "danger";
4
+ export interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
5
+ variant?: 'default' | 'danger'
7
6
  }
8
7
 
9
8
  const ActionButton = ({
10
- variant = "default",
9
+ variant = 'default',
11
10
  className,
12
11
  children,
13
12
  ...rest
14
13
  }: ActionButtonProps) => {
15
- const isDanger = variant === "danger";
14
+ const isDanger = variant === 'danger'
16
15
  return (
17
16
  <button
18
17
  type="button"
19
18
  className={classNames(
20
- "flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors focus-ring disabled:cursor-not-allowed disabled:opacity-60",
19
+ 'flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors focus-ring disabled:cursor-not-allowed disabled:opacity-60',
21
20
  isDanger
22
- ? "text-danger hover:bg-danger/50"
23
- : "text-charcoal hover:bg-sand",
24
- className,
21
+ ? 'text-danger hover:bg-danger/50'
22
+ : 'text-charcoal hover:bg-sand',
23
+ className
25
24
  )}
26
25
  {...rest}
27
26
  >
28
27
  {children}
29
28
  </button>
30
- );
31
- };
29
+ )
30
+ }
32
31
 
33
- export default ActionButton;
32
+ export default ActionButton
@@ -184,9 +184,7 @@ export const AllVariants: StoryFn = () => {
184
184
  variant: 'dark',
185
185
  mimeType: 'image/png',
186
186
  detail: '1.1 MB',
187
- thumbnail: (
188
- <AttachmentThumbnail mimeType="image/png" variant="dark" />
189
- ),
187
+ thumbnail: <AttachmentThumbnail mimeType="image/png" variant="dark" />,
190
188
  },
191
189
  },
192
190
  {
@@ -7,11 +7,7 @@ import { renderTypeIcon } from './utils/icons'
7
7
  import { getSourceType } from './utils/mimeType'
8
8
 
9
9
  type TouchEventUnion =
10
- | MouseEvent
11
- | TouchEvent
12
- | React.MouseEvent
13
- | React.TouchEvent
14
-
10
+ MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent
15
11
 
16
12
  const getClientXFromEvent = (e: TouchEventUnion): number => {
17
13
  if ('touches' in e) {
@@ -194,14 +190,20 @@ const MediaPlayer: React.FC<MediaPlayerProps> = ({
194
190
  className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}
195
191
  style={aspectStyle}
196
192
  onClick={(e) => {
197
- if (onContainerClick) { onContainerClick(e); return }
193
+ if (onContainerClick) {
194
+ onContainerClick(e)
195
+ return
196
+ }
198
197
  if (manualPlayRequired) return
199
198
  if (controls) setPlaying((p) => !p)
200
199
  }}
201
200
  onKeyDown={(e) => {
202
201
  if (e.key !== 'Enter' && e.key !== ' ') return
203
202
  e.preventDefault()
204
- if (onContainerClick) { onContainerClick(e as unknown as React.MouseEvent); return }
203
+ if (onContainerClick) {
204
+ onContainerClick(e as unknown as React.MouseEvent)
205
+ return
206
+ }
205
207
  if (manualPlayRequired) return
206
208
  if (controls) setPlaying((p) => !p)
207
209
  }}
@@ -61,10 +61,14 @@ const AttachmentCard: React.FC<AttachmentCardProps> = ({
61
61
  )}
62
62
  >
63
63
  {topLeft ? (
64
- <div className="pointer-events-auto absolute left-3 top-3 z-50">{topLeft}</div>
64
+ <div className="pointer-events-auto absolute left-3 top-3 z-50">
65
+ {topLeft}
66
+ </div>
65
67
  ) : null}
66
68
  {topRight ? (
67
- <div className="pointer-events-auto absolute right-3 top-3 z-50">{topRight}</div>
69
+ <div className="pointer-events-auto absolute right-3 top-3 z-50">
70
+ {topRight}
71
+ </div>
68
72
  ) : null}
69
73
 
70
74
  {thumbnail}
@@ -9,8 +9,8 @@ const meta: Meta<ComponentProps> = {
9
9
  title: 'Avatar',
10
10
  component: Avatar,
11
11
  parameters: {
12
- layout: 'centered'
13
- }
12
+ layout: 'centered',
13
+ },
14
14
  }
15
15
  export default meta
16
16
 
@@ -138,11 +138,23 @@ export const DifferentColors: StoryFn = () => {
138
138
  // pravatar avatar flake doesn't diff the whole grid.
139
139
  export const MixedAvatars: StoryFn = () => {
140
140
  const users = [
141
- { id: 'user-1', name: 'Alice Anderson', image: 'https://i.pravatar.cc/150?img=1' },
141
+ {
142
+ id: 'user-1',
143
+ name: 'Alice Anderson',
144
+ image: 'https://i.pravatar.cc/150?img=1',
145
+ },
142
146
  { id: 'user-2', name: 'Bob Brown' },
143
- { id: 'user-3', name: 'Carol Chen', image: 'https://i.pravatar.cc/150?img=3' },
147
+ {
148
+ id: 'user-3',
149
+ name: 'Carol Chen',
150
+ image: 'https://i.pravatar.cc/150?img=3',
151
+ },
144
152
  { id: 'user-4', name: 'David Davis' },
145
- { id: 'user-5', name: 'Emma Evans', image: 'https://i.pravatar.cc/150?img=5' },
153
+ {
154
+ id: 'user-5',
155
+ name: 'Emma Evans',
156
+ image: 'https://i.pravatar.cc/150?img=5',
157
+ },
146
158
  { id: 'user-6', name: 'Frank Foster' },
147
159
  ]
148
160
 
@@ -47,18 +47,12 @@ export const Avatar = ({
47
47
  const aiBorderWidth = size >= 40 ? 2 : 1
48
48
 
49
49
  const borderStyle =
50
- shape === 'circle'
51
- ? { borderRadius: '50%' }
52
- : { borderRadius: '1rem' }
50
+ shape === 'circle' ? { borderRadius: '50%' } : { borderRadius: '1rem' }
53
51
 
54
52
  const avatarInner = (
55
53
  <div className="h-full w-full overflow-hidden" style={borderStyle}>
56
54
  {image ? (
57
- <img
58
- src={image}
59
- alt=""
60
- className="h-full w-full object-cover"
61
- />
55
+ <img src={image} alt="" className="h-full w-full object-cover" />
62
56
  ) : (
63
57
  <div
64
58
  aria-hidden="true"
@@ -75,17 +69,16 @@ export const Avatar = ({
75
69
 
76
70
  return (
77
71
  <div
78
- className={classNames(
79
- 'relative flex-shrink-0',
80
- className
81
- )}
82
- style={{
83
- '--str-chat__avatar-size': `${size}px`,
84
- width: `${size}px`,
85
- height: `${size}px`,
86
- backgroundColor: image ? undefined : bgColor,
87
- ...borderStyle,
88
- } as React.CSSProperties}
72
+ className={classNames('relative flex-shrink-0', className)}
73
+ style={
74
+ {
75
+ '--str-chat__avatar-size': `${size}px`,
76
+ width: `${size}px`,
77
+ height: `${size}px`,
78
+ backgroundColor: image ? undefined : bgColor,
79
+ ...borderStyle,
80
+ } as React.CSSProperties
81
+ }
89
82
  >
90
83
  {starred && (
91
84
  <div
@@ -97,10 +90,7 @@ export const Avatar = ({
97
90
  )}
98
91
  <div
99
92
  data-testid="avatar-ring"
100
- className={classNames(
101
- 'h-full w-full',
102
- 'bg-transparent'
103
- )}
93
+ className={classNames('h-full w-full', 'bg-transparent')}
104
94
  style={{
105
95
  ...borderStyle,
106
96
  ...(dmAgentEnabled && {
@@ -345,12 +345,10 @@ describe('ChannelView', () => {
345
345
  const firstHandler = vi.fn()
346
346
  const secondHandler = vi.fn()
347
347
  const { rerender: rerenderChannel } = renderWithProviders(
348
- <ChannelView
349
- channel={createChannel()}
350
- onBroadcastClick={firstHandler}
351
- />
348
+ <ChannelView channel={createChannel()} onBroadcastClick={firstHandler} />
352
349
  )
353
- const firstMessageOverride = activeComponentOverrides.Message as React.ComponentType
350
+ const firstMessageOverride =
351
+ activeComponentOverrides.Message as React.ComponentType
354
352
  const MessageRowHarness = ({
355
353
  Message,
356
354
  }: {
@@ -363,12 +361,10 @@ describe('ChannelView', () => {
363
361
  expect(customMessageMounts).toHaveBeenCalledOnce()
364
362
 
365
363
  rerenderChannel(
366
- <ChannelView
367
- channel={createChannel()}
368
- onBroadcastClick={secondHandler}
369
- />
364
+ <ChannelView channel={createChannel()} onBroadcastClick={secondHandler} />
370
365
  )
371
- const secondMessageOverride = activeComponentOverrides.Message as React.ComponentType
366
+ const secondMessageOverride =
367
+ activeComponentOverrides.Message as React.ComponentType
372
368
 
373
369
  expect(secondMessageOverride).toBe(firstMessageOverride)
374
370
  rerenderMessageRow(<MessageRowHarness Message={secondMessageOverride} />)
@@ -26,7 +26,10 @@ import { createMockStreamChatClient } from '../../testing/createMockStreamChatCl
26
26
  import type { BroadcastNameResolver } from '../../types'
27
27
  import CustomTypingIndicator from '../CustomTypingIndicator'
28
28
 
29
- import { BroadcastNameContext, buildBroadcastNamesById } from './BroadcastNameContext'
29
+ import {
30
+ BroadcastNameContext,
31
+ buildBroadcastNamesById,
32
+ } from './BroadcastNameContext'
30
33
  import { CustomMessageActions } from './CustomMessageActions'
31
34
 
32
35
  import { CustomMessage } from './index'
@@ -307,7 +310,9 @@ BroadcastStatus.args = {
307
310
  ],
308
311
  }
309
312
 
310
- export const BroadcastStatusNonLatest: StoryFn<TemplateProps> = Template.bind({})
313
+ export const BroadcastStatusNonLatest: StoryFn<TemplateProps> = Template.bind(
314
+ {}
315
+ )
311
316
  BroadcastStatusNonLatest.args = {
312
317
  messages: [
313
318
  {
@@ -130,9 +130,11 @@ describe('CustomMessage', () => {
130
130
  )
131
131
 
132
132
  rerender(<CustomMessage onBroadcastClick={secondHandler} />)
133
- screen.getByRole('button', {
134
- name: 'View broadcast July 9th Class attendees',
135
- }).click()
133
+ screen
134
+ .getByRole('button', {
135
+ name: 'View broadcast July 9th Class attendees',
136
+ })
137
+ .click()
136
138
 
137
139
  expect(firstHandler).not.toHaveBeenCalled()
138
140
  expect(secondHandler).toHaveBeenCalledWith({
@@ -21,7 +21,10 @@ describe('LockedAttachment (characterization)', () => {
21
21
 
22
22
  it('media mode: renders a preview toggle when a source fetcher is wired', () => {
23
23
  renderWithProviders(
24
- <MediaCard isDraft onFetchSource={vi.fn().mockResolvedValue(undefined)} />
24
+ <MediaCard
25
+ isDraft
26
+ onFetchSource={vi.fn().mockResolvedValue(undefined)}
27
+ />
25
28
  )
26
29
  expect(
27
30
  screen.getByRole('button', { name: 'Toggle preview' })
@@ -88,9 +91,7 @@ describe('LockedAttachment (characterization)', () => {
88
91
  <MediaCard isMine={false} amountText="$5" onUnlockClick={vi.fn()} />
89
92
  )
90
93
  expect(screen.getByTestId('locked-attachment')).toBeInTheDocument()
91
- expect(
92
- screen.getByRole('button', { name: 'Unlock' })
93
- ).toBeInTheDocument()
94
+ expect(screen.getByRole('button', { name: 'Unlock' })).toBeInTheDocument()
94
95
  })
95
96
  })
96
97
 
@@ -24,7 +24,7 @@ const DraftTextCard: React.FC<TextCardDraftProps> = ({
24
24
  onDismiss,
25
25
  }) => (
26
26
  <TextShell isMine className="pr-8">
27
- {renderedText || <SkeletonTextLines variant="dark" />}
27
+ {renderedText || <SkeletonTextLines variant="dark" />}
28
28
  <PriceLockRow>
29
29
  <span className={amountText ? 'text-white/55' : 'text-white/30'}>
30
30
  {amountText || placeholderAmountText}
@@ -100,9 +100,7 @@ const OtherTextCard: React.FC<TextCardOtherProps> = ({
100
100
  )
101
101
  }
102
102
 
103
- const ariaLabel = isUnlocking
104
- ? 'Unlocking message.'
105
- : 'Unlock this message.'
103
+ const ariaLabel = isUnlocking ? 'Unlocking message.' : 'Unlock this message.'
106
104
 
107
105
  return (
108
106
  <TextShell isMine={false}>
@@ -55,12 +55,15 @@ const CardBody: React.FC<CardBodyProps> = ({
55
55
  <div className="flex min-w-0 flex-1 flex-col gap-1">
56
56
  {displayTitle.trim() !== '' && (
57
57
  <p
58
- className={classNames('truncate text-base font-medium leading-6', {
59
- 'text-black/90': !isDark && !titleDimmed,
60
- 'text-black/30': !isDark && titleDimmed,
61
- 'text-white/30': isDark && titleDimmed,
62
- 'text-white': isDark && !titleDimmed,
63
- })}
58
+ className={classNames(
59
+ 'truncate text-base font-medium leading-6',
60
+ {
61
+ 'text-black/90': !isDark && !titleDimmed,
62
+ 'text-black/30': !isDark && titleDimmed,
63
+ 'text-white/30': isDark && titleDimmed,
64
+ 'text-white': isDark && !titleDimmed,
65
+ }
66
+ )}
64
67
  >
65
68
  {displayTitle}
66
69
  </p>
@@ -36,9 +36,7 @@ export const isGalleryCard = (
36
36
  * otherwise auto-detects the icon from `mimeType`. Returned as a ready node so
37
37
  * every card shares the same size/tone treatment.
38
38
  */
39
- export const galleryBodyIcon = (
40
- variant: CardVariant
41
- ): React.ReactNode => (
39
+ export const galleryBodyIcon = (variant: CardVariant): React.ReactNode => (
42
40
  <ImagesIcon
43
41
  className={
44
42
  variant === 'dark'
@@ -4,10 +4,7 @@ import React, { useState } from 'react'
4
4
 
5
5
  import { optimizeMessagingAttachmentUrl } from '../../../../../utils/cdnImageUrl'
6
6
  import { AttachmentThumbnail, getSourceType } from '../../../../AttachmentCard'
7
- import type {
8
- LockedAttachmentGalleryItem,
9
- PaymentStatus,
10
- } from '../../types'
7
+ import type { LockedAttachmentGalleryItem, PaymentStatus } from '../../types'
11
8
 
12
9
  import { LockBadge } from './LockBadge'
13
10
  import type { CardVariant } from './MediaShell'
@@ -54,7 +54,6 @@ const PurchaseStatusBadge: React.FC<PurchaseStatusBadgeProps> = ({
54
54
  )
55
55
  }
56
56
 
57
-
58
57
  if (paymentStatus === 'failed' || paymentStatus === 'refunded') {
59
58
  return (
60
59
  <React.Fragment>
@@ -2,10 +2,7 @@ import classNames from 'classnames'
2
2
  import React from 'react'
3
3
 
4
4
  import { optimizeMessagingAttachmentUrl } from '../../../../../utils/cdnImageUrl'
5
- import {
6
- AttachmentThumbnail,
7
- renderTypeIcon,
8
- } from '../../../../AttachmentCard'
5
+ import { AttachmentThumbnail, renderTypeIcon } from '../../../../AttachmentCard'
9
6
  import type { LockedAttachmentSource, PaymentStatus } from '../../types'
10
7
 
11
8
  import { LockBadge } from './LockBadge'
@@ -15,11 +15,16 @@ export interface SkeletonTextLinesProps {
15
15
  * support opacity modifiers on the `current` color — `bg-current/30` silently
16
16
  * produces no CSS rule at all.
17
17
  */
18
- const SkeletonTextLines: React.FC<SkeletonTextLinesProps> = ({ variant = 'dark' }) => {
18
+ const SkeletonTextLines: React.FC<SkeletonTextLinesProps> = ({
19
+ variant = 'dark',
20
+ }) => {
19
21
  const colour = variant === 'dark' ? 'bg-white/25' : 'bg-black/15'
20
22
 
21
23
  return (
22
- <div className="flex flex-col gap-2 str-chat__message-text my-1 animate-pulse" aria-hidden>
24
+ <div
25
+ className="flex flex-col gap-2 str-chat__message-text my-1 animate-pulse"
26
+ aria-hidden
27
+ >
23
28
  <div className={classNames('h-3 w-40 rounded-full', colour)} />
24
29
  <div className={classNames('h-3 w-24 rounded-full', colour)} />
25
30
  </div>
@@ -39,6 +39,7 @@ export interface LockedAttachmentContextValue {
39
39
  ) => Promise<LockedAttachmentSource | void>
40
40
  }
41
41
 
42
- export const defaultLockedAttachmentContextValue: LockedAttachmentContextValue = {
43
- isUnlocking: () => false,
44
- }
42
+ export const defaultLockedAttachmentContextValue: LockedAttachmentContextValue =
43
+ {
44
+ isUnlocking: () => false,
45
+ }