@linktr.ee/messaging-react 3.4.0-rc-1782387968 → 3.4.0-rc-1782392192
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/{Card-utKbCGom.cjs → Card-6snF25TP.cjs} +2 -2
- package/dist/{Card-utKbCGom.cjs.map → Card-6snF25TP.cjs.map} +1 -1
- package/dist/{Card-UbPYWjnX.cjs → Card-BTbz8XCg.cjs} +2 -2
- package/dist/{Card-UbPYWjnX.cjs.map → Card-BTbz8XCg.cjs.map} +1 -1
- package/dist/{Card-beoX9cug.js → Card-CBi3z_Wt.js} +2 -2
- package/dist/{Card-beoX9cug.js.map → Card-CBi3z_Wt.js.map} +1 -1
- package/dist/{Card-BOD2Qo_b.js → Card-Cbw4GBkm.js} +3 -3
- package/dist/{Card-BOD2Qo_b.js.map → Card-Cbw4GBkm.js.map} +1 -1
- package/dist/{Card-DcEBssw0.js → Card-D3-jTRWp.js} +2 -2
- package/dist/{Card-DcEBssw0.js.map → Card-D3-jTRWp.js.map} +1 -1
- package/dist/{Card-DkNdLpVE.cjs → Card-DdK8Vv7y.cjs} +2 -2
- package/dist/{Card-DkNdLpVE.cjs.map → Card-DdK8Vv7y.cjs.map} +1 -1
- package/dist/{LockedThumbnail-Bjdf-fTw.cjs → LockedThumbnail-Cih__olI.cjs} +2 -2
- package/dist/{LockedThumbnail-Bjdf-fTw.cjs.map → LockedThumbnail-Cih__olI.cjs.map} +1 -1
- package/dist/{LockedThumbnail-bOjjYYyV.js → LockedThumbnail-qPBaTZon.js} +2 -2
- package/dist/{LockedThumbnail-bOjjYYyV.js.map → LockedThumbnail-qPBaTZon.js.map} +1 -1
- package/dist/{index-DG5LOHey.js → index-BOsrtjME.js} +1031 -1008
- package/dist/index-BOsrtjME.js.map +1 -0
- package/dist/index-DQk6hOJg.cjs +2 -0
- package/dist/index-DQk6hOJg.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +10 -18
- package/dist/index.js +19 -20
- package/package.json +2 -2
- package/src/components/ChannelList/CustomChannelPreview.test.tsx +0 -38
- package/src/components/ChannelList/CustomChannelPreview.tsx +6 -5
- package/src/components/ChannelView.stories.tsx +16 -0
- package/src/components/ChannelView.test.tsx +20 -35
- package/src/components/ChannelView.tsx +55 -17
- package/src/index.ts +0 -2
- package/src/stream-custom-data.ts +0 -8
- package/src/types.ts +11 -0
- package/dist/index-B3oQq9zK.cjs +0 -2
- package/dist/index-B3oQq9zK.cjs.map +0 -1
- package/dist/index-DG5LOHey.js.map +0 -1
- package/src/components/VerifiedBadge/index.tsx +0 -25
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DQk6hOJg.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.MessageVoteButtons=e.MessageVoteButtons;exports.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.buildCompactMetaLabel=e.buildCompactMetaLabel;exports.formatFileSize=e.formatFileSize;exports.formatRelativeTime=e.formatRelativeTime;exports.getFileExtensionLabel=e.getFileExtensionLabel;exports.getMessageDisplayText=e.getMessageDisplayText;exports.isLinkAttachment=e.isLinkAttachment;exports.isUuidLike=e.isUuidLike;exports.messageAttachmentGroupPositionFromStream=e.bubbleGroupPositionFromStream;exports.normalizeLanguageCode=e.normalizeLanguageCode;exports.resolveLinkAttachment=e.resolveLinkAttachment;exports.resolveMediaFromMessage=e.resolveMediaFromMessage;exports.resolveParticipantDisplayName=e.resolveParticipantDisplayName;exports.useCustomMessage=e.useCustomMessage;exports.useMessageVote=e.useMessageVote;exports.useMessaging=e.useMessaging;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -351,6 +351,16 @@ export declare interface ChannelViewProps {
|
|
|
351
351
|
* Use this to render staged paid or media attachments inside the input.
|
|
352
352
|
*/
|
|
353
353
|
attachmentPreviewList?: ComponentType;
|
|
354
|
+
/**
|
|
355
|
+
* Fired when the participant's name in the channel header is clicked. When
|
|
356
|
+
* provided, the name renders as a button with a trailing caret (an affordance
|
|
357
|
+
* for opening participant details / thread content); when omitted, the name
|
|
358
|
+
* renders as plain text.
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* onParticipantNameClick={() => openThreadContentDialog()}
|
|
362
|
+
*/
|
|
363
|
+
onParticipantNameClick?: () => void;
|
|
354
364
|
}
|
|
355
365
|
|
|
356
366
|
export declare interface ComposerCardProps extends LockedAttachmentBaseProps {
|
|
@@ -1389,17 +1399,6 @@ declare interface UseMessageVoteResult {
|
|
|
1389
1399
|
*/
|
|
1390
1400
|
export declare const useMessaging: () => MessagingContextValue;
|
|
1391
1401
|
|
|
1392
|
-
/**
|
|
1393
|
-
* Linktree verification badge shown next to the name of a verified profile.
|
|
1394
|
-
* Rendered when a participant's Stream user has `is_verified` set to true.
|
|
1395
|
-
*/
|
|
1396
|
-
export declare const VerifiedBadge: default_2.FC<VerifiedBadgeProps>;
|
|
1397
|
-
|
|
1398
|
-
export declare interface VerifiedBadgeProps {
|
|
1399
|
-
className?: string;
|
|
1400
|
-
size?: number;
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
1402
|
declare interface VideoAttachmentSharedProps extends MessageAttachmentBaseProps {
|
|
1404
1403
|
/** Single video — convenience for the most common case. */
|
|
1405
1404
|
src?: string;
|
|
@@ -1472,13 +1471,6 @@ declare module 'stream-chat' {
|
|
|
1472
1471
|
*/
|
|
1473
1472
|
chatbot_paused?: boolean;
|
|
1474
1473
|
}
|
|
1475
|
-
interface CustomUserData {
|
|
1476
|
-
/**
|
|
1477
|
-
* Whether the user is a verified Linktree profile. When true, a
|
|
1478
|
-
* verification badge is shown next to their name in messaging.
|
|
1479
|
-
*/
|
|
1480
|
-
is_verified?: boolean;
|
|
1481
|
-
}
|
|
1482
1474
|
interface CustomMessageData {
|
|
1483
1475
|
/**
|
|
1484
1476
|
* When true, hides the date timestamp in system messages.
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as e, b as t, C as i, c as n, d as o, e as m, F as g, f as l, L as r, h as M, M as u, i as L, j as c, k as h, l as d, m as p, n as v, o as A, p as C, q as F, s as k, t as b, u as f, v as x, w as y, x as P, y as S, z as q, B as z, D as B } from "./index-BOsrtjME.js";
|
|
2
2
|
export {
|
|
3
|
-
|
|
3
|
+
e as ActionButton,
|
|
4
4
|
t as Avatar,
|
|
5
5
|
i as ChannelEmptyState,
|
|
6
6
|
n as ChannelList,
|
|
7
7
|
o as ChannelView,
|
|
8
8
|
m as CustomMessageProvider,
|
|
9
9
|
g as FaqList,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
l as FaqListItem,
|
|
11
|
+
r as LinkAttachment,
|
|
12
12
|
M as LockedAttachment,
|
|
13
13
|
u as MediaMessage,
|
|
14
14
|
L as MessageAttachment,
|
|
15
15
|
c as MessageVoteButtons,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
p as
|
|
19
|
-
v as
|
|
20
|
-
A as
|
|
21
|
-
C as
|
|
22
|
-
F as
|
|
23
|
-
k as
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
b as messageAttachmentGroupPositionFromStream,
|
|
16
|
+
h as MessagingProvider,
|
|
17
|
+
d as MessagingShell,
|
|
18
|
+
p as buildCompactMetaLabel,
|
|
19
|
+
v as formatFileSize,
|
|
20
|
+
A as formatRelativeTime,
|
|
21
|
+
C as getFileExtensionLabel,
|
|
22
|
+
F as getMessageDisplayText,
|
|
23
|
+
k as isLinkAttachment,
|
|
24
|
+
b as isUuidLike,
|
|
25
|
+
f as messageAttachmentGroupPositionFromStream,
|
|
27
26
|
x as normalizeLanguageCode,
|
|
28
27
|
y as resolveLinkAttachment,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
P as resolveMediaFromMessage,
|
|
29
|
+
S as resolveParticipantDisplayName,
|
|
30
|
+
q as useCustomMessage,
|
|
31
|
+
z as useMessageVote,
|
|
32
|
+
B as useMessaging
|
|
34
33
|
};
|
|
35
34
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/messaging-react",
|
|
3
|
-
"version": "3.4.0-rc-
|
|
3
|
+
"version": "3.4.0-rc-1782392192",
|
|
4
4
|
"description": "React messaging components built on messaging-core for web applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@linktr.ee/component-library": "11.8.6",
|
|
41
|
-
"@linktr.ee/messaging-core": "2.3.0-rc-
|
|
41
|
+
"@linktr.ee/messaging-core": "2.3.0-rc-1782392192",
|
|
42
42
|
"@phosphor-icons/react": "^2.1.10"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
@@ -101,44 +101,6 @@ describe('CustomChannelPreview', () => {
|
|
|
101
101
|
expect(screen.getByText('Unknown member')).toBeInTheDocument()
|
|
102
102
|
})
|
|
103
103
|
|
|
104
|
-
it('shows the verification badge when the participant is verified', () => {
|
|
105
|
-
const channel = createMockChannel([])
|
|
106
|
-
channel.state.members['participant-1'] = {
|
|
107
|
-
user: { id: 'participant-1', name: 'Alice', is_verified: true },
|
|
108
|
-
user_id: 'participant-1',
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
renderWithProviders(
|
|
112
|
-
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
expect(screen.getByLabelText('Verified')).toBeInTheDocument()
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('does not show the verification badge when the participant is not verified', () => {
|
|
119
|
-
const channel = createMockChannel([])
|
|
120
|
-
channel.state.members['participant-1'] = {
|
|
121
|
-
user: { id: 'participant-1', name: 'Alice', is_verified: false },
|
|
122
|
-
user_id: 'participant-1',
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
renderWithProviders(
|
|
126
|
-
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
expect(screen.queryByLabelText('Verified')).not.toBeInTheDocument()
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('does not show the verification badge when is_verified is absent', () => {
|
|
133
|
-
const channel = createMockChannel([])
|
|
134
|
-
|
|
135
|
-
renderWithProviders(
|
|
136
|
-
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
expect(screen.queryByLabelText('Verified')).not.toBeInTheDocument()
|
|
140
|
-
})
|
|
141
|
-
|
|
142
104
|
it('shows the latest non-system message when the last message is a system message', () => {
|
|
143
105
|
const channel = createMockChannel([
|
|
144
106
|
{
|
|
@@ -8,7 +8,6 @@ import { getMessageDisplayText } from '../../utils/getMessageDisplayText'
|
|
|
8
8
|
import { resolveParticipantDisplayName } from '../../utils/resolveParticipantDisplayName'
|
|
9
9
|
import { Avatar } from '../Avatar'
|
|
10
10
|
import { isChatbotMessage } from '../CustomMessage/MessageTag'
|
|
11
|
-
import { VerifiedBadge } from '../VerifiedBadge'
|
|
12
11
|
|
|
13
12
|
import { useChannelListContext } from './ChannelListContext'
|
|
14
13
|
|
|
@@ -49,7 +48,6 @@ const CustomChannelPreview = React.memo<ChannelPreviewUIComponentProps>(
|
|
|
49
48
|
)
|
|
50
49
|
const participantName = resolveParticipantDisplayName(participant?.user)
|
|
51
50
|
const participantImage = participant?.user?.image
|
|
52
|
-
const isParticipantVerified = participant?.user?.is_verified === true
|
|
53
51
|
|
|
54
52
|
// Get last non-system message for preview
|
|
55
53
|
const lastMessage = (() => {
|
|
@@ -148,12 +146,15 @@ const CustomChannelPreview = React.memo<ChannelPreviewUIComponentProps>(
|
|
|
148
146
|
<div className="flex-1 min-w-0 flex flex-col gap-1">
|
|
149
147
|
{/* Name and timestamp row */}
|
|
150
148
|
<div className="flex items-center justify-between gap-2">
|
|
151
|
-
<h3
|
|
149
|
+
<h3
|
|
150
|
+
className={classNames(
|
|
151
|
+
'text-sm font-medium truncate text-[#191918]'
|
|
152
|
+
)}
|
|
153
|
+
>
|
|
152
154
|
{isChannelStarred && (
|
|
153
155
|
<span className="sr-only">Starred conversation. </span>
|
|
154
156
|
)}
|
|
155
|
-
|
|
156
|
-
{isParticipantVerified && <VerifiedBadge />}
|
|
157
|
+
{participantName}
|
|
157
158
|
</h3>
|
|
158
159
|
{lastMessageTime && (
|
|
159
160
|
<span className="text-xs text-[#717070] flex-shrink-0">
|
|
@@ -251,6 +251,22 @@ Default.parameters = {
|
|
|
251
251
|
},
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
export const ParticipantNameTrigger: StoryFn<TemplateProps> = Template.bind({})
|
|
255
|
+
ParticipantNameTrigger.args = {
|
|
256
|
+
showBackButton: false,
|
|
257
|
+
onParticipantNameClick: () =>
|
|
258
|
+
// eslint-disable-next-line no-alert
|
|
259
|
+
window.alert('Participant name clicked — open Thread content'),
|
|
260
|
+
}
|
|
261
|
+
ParticipantNameTrigger.parameters = {
|
|
262
|
+
docs: {
|
|
263
|
+
description: {
|
|
264
|
+
story:
|
|
265
|
+
'Header with `onParticipantNameClick` set: the participant name renders as a button with a trailing caret (both the mobile and desktop header layouts). Click the name to fire the callback (shows an alert here). With the prop omitted (see Default) the name is plain, non-interactive text.',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
|
|
254
270
|
export const DmAgentHeader: StoryFn<TemplateProps> = Template.bind({})
|
|
255
271
|
DmAgentHeader.args = {
|
|
256
272
|
showBackButton: false,
|
|
@@ -106,7 +106,6 @@ const createChannel = ({
|
|
|
106
106
|
name?: string
|
|
107
107
|
username?: string
|
|
108
108
|
is_account?: boolean
|
|
109
|
-
is_verified?: boolean
|
|
110
109
|
}
|
|
111
110
|
} = {}) =>
|
|
112
111
|
({
|
|
@@ -194,6 +193,26 @@ describe('ChannelView', () => {
|
|
|
194
193
|
expect(screen.getAllByText('Linker').length).toBeGreaterThanOrEqual(1)
|
|
195
194
|
})
|
|
196
195
|
|
|
196
|
+
it('renders the participant name as a button that fires onParticipantNameClick', () => {
|
|
197
|
+
const onParticipantNameClick = vi.fn()
|
|
198
|
+
renderWithProviders(
|
|
199
|
+
<ChannelView
|
|
200
|
+
channel={createChannel()}
|
|
201
|
+
onParticipantNameClick={onParticipantNameClick}
|
|
202
|
+
/>
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
// Both the mobile and desktop header layouts render the button (one is
|
|
206
|
+
// hidden via CSS), so there is at least one match.
|
|
207
|
+
const buttons = screen.getAllByRole('button', {
|
|
208
|
+
name: /view details for linker/i,
|
|
209
|
+
})
|
|
210
|
+
expect(buttons.length).toBeGreaterThanOrEqual(1)
|
|
211
|
+
|
|
212
|
+
buttons[0].click()
|
|
213
|
+
expect(onParticipantNameClick).toHaveBeenCalledTimes(1)
|
|
214
|
+
})
|
|
215
|
+
|
|
197
216
|
it('renders the actions menu by default', () => {
|
|
198
217
|
renderWithProviders(<ChannelView channel={createChannel()} />)
|
|
199
218
|
|
|
@@ -456,40 +475,6 @@ describe('ChannelView', () => {
|
|
|
456
475
|
expect(screen.getAllByText('Unknown member').length).toBeGreaterThan(0)
|
|
457
476
|
})
|
|
458
477
|
|
|
459
|
-
it('shows the verification badge in the header when the participant is verified', () => {
|
|
460
|
-
renderWithProviders(
|
|
461
|
-
<ChannelView
|
|
462
|
-
channel={createChannel({
|
|
463
|
-
otherUser: {
|
|
464
|
-
id: 'linker-1',
|
|
465
|
-
name: 'Linker',
|
|
466
|
-
is_account: true,
|
|
467
|
-
is_verified: true,
|
|
468
|
-
},
|
|
469
|
-
})}
|
|
470
|
-
/>
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
expect(screen.getAllByLabelText('Verified').length).toBeGreaterThan(0)
|
|
474
|
-
})
|
|
475
|
-
|
|
476
|
-
it('does not show the verification badge in the header when the participant is not verified', () => {
|
|
477
|
-
renderWithProviders(
|
|
478
|
-
<ChannelView
|
|
479
|
-
channel={createChannel({
|
|
480
|
-
otherUser: {
|
|
481
|
-
id: 'linker-1',
|
|
482
|
-
name: 'Linker',
|
|
483
|
-
is_account: true,
|
|
484
|
-
is_verified: false,
|
|
485
|
-
},
|
|
486
|
-
})}
|
|
487
|
-
/>
|
|
488
|
-
)
|
|
489
|
-
|
|
490
|
-
expect(screen.queryByLabelText('Verified')).not.toBeInTheDocument()
|
|
491
|
-
})
|
|
492
|
-
|
|
493
478
|
it('fires onMessageLinkClick with the href and undefined message when the link is not inside a message wrapper', () => {
|
|
494
479
|
const handler = vi.fn()
|
|
495
480
|
const { container } = renderWithProviders(
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ArrowLeftIcon,
|
|
3
|
+
CaretRightIcon,
|
|
4
|
+
SparkleIcon,
|
|
5
|
+
StarIcon,
|
|
6
|
+
} from '@phosphor-icons/react'
|
|
2
7
|
import classNames from 'classnames'
|
|
3
8
|
import React, { useCallback, useEffect, useRef } from 'react'
|
|
4
9
|
import { Channel as ChannelType } from 'stream-chat'
|
|
@@ -27,7 +32,6 @@ import CustomTypingIndicator from './CustomTypingIndicator'
|
|
|
27
32
|
import { DmAgentEnabledContext } from './CustomTypingIndicator/DmAgentContext'
|
|
28
33
|
import { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'
|
|
29
34
|
import { LoadingState } from './MessagingShell/LoadingState'
|
|
30
|
-
import { VerifiedBadge } from './VerifiedBadge'
|
|
31
35
|
|
|
32
36
|
const ICON_BTN_CLASS =
|
|
33
37
|
'size-10 rounded-full hover:bg-[#E5E4E1] flex items-center justify-center transition-colors duration-150 focus-ring'
|
|
@@ -53,6 +57,7 @@ const CustomChannelHeader: React.FC<{
|
|
|
53
57
|
customChannelActions?: React.ReactNode
|
|
54
58
|
renderChannelActions?: React.ReactNode
|
|
55
59
|
showChannelInfo?: boolean
|
|
60
|
+
onParticipantNameClick?: () => void
|
|
56
61
|
renderHeaderTitleBadges?: ChannelViewProps['renderHeaderTitleBadges']
|
|
57
62
|
}> = ({
|
|
58
63
|
onBack,
|
|
@@ -70,6 +75,7 @@ const CustomChannelHeader: React.FC<{
|
|
|
70
75
|
customChannelActions,
|
|
71
76
|
renderChannelActions,
|
|
72
77
|
showChannelInfo = true,
|
|
78
|
+
onParticipantNameClick,
|
|
73
79
|
renderHeaderTitleBadges,
|
|
74
80
|
}) => {
|
|
75
81
|
const { channel } = useChannelStateContext()
|
|
@@ -86,7 +92,6 @@ const CustomChannelHeader: React.FC<{
|
|
|
86
92
|
|
|
87
93
|
const participantName = resolveParticipantDisplayName(participant?.user)
|
|
88
94
|
const participantImage = participant?.user?.image
|
|
89
|
-
const isParticipantVerified = participant?.user?.is_verified === true
|
|
90
95
|
const isStarred = useChannelStar(channel)
|
|
91
96
|
const headerTitleBadges = renderHeaderTitleBadges?.({
|
|
92
97
|
channel,
|
|
@@ -135,13 +140,27 @@ const CustomChannelHeader: React.FC<{
|
|
|
135
140
|
dmAgentEnabled={dmAgentEnabled}
|
|
136
141
|
size={48}
|
|
137
142
|
/>
|
|
138
|
-
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
{onParticipantNameClick ? (
|
|
144
|
+
<button
|
|
145
|
+
type="button"
|
|
146
|
+
onClick={onParticipantNameClick}
|
|
147
|
+
aria-label={`View details for ${participantName}`}
|
|
148
|
+
className="flex max-w-full items-center gap-0.5 rounded text-center text-xs font-medium text-black/90 transition-opacity hover:opacity-70"
|
|
149
|
+
>
|
|
150
|
+
<span className="min-w-0 truncate">{participantName}</span>
|
|
151
|
+
{headerTitleBadges && (
|
|
152
|
+
<span className="shrink-0">{headerTitleBadges}</span>
|
|
153
|
+
)}
|
|
154
|
+
<CaretRightIcon className="size-3 shrink-0" weight="bold" />
|
|
155
|
+
</button>
|
|
156
|
+
) : (
|
|
157
|
+
<p className="flex max-w-full items-center justify-center gap-1 text-center text-xs font-medium text-black/90">
|
|
158
|
+
<span className="min-w-0 truncate">{participantName}</span>
|
|
159
|
+
{headerTitleBadges && (
|
|
160
|
+
<span className="shrink-0">{headerTitleBadges}</span>
|
|
161
|
+
)}
|
|
162
|
+
</p>
|
|
163
|
+
)}
|
|
145
164
|
{dmAgentEnabled && (
|
|
146
165
|
<div className="flex items-center gap-1 text-[10px] leading-3 text-black/55">
|
|
147
166
|
<SparkleIcon className="size-3 shrink-0 text-black/55" />
|
|
@@ -214,13 +233,27 @@ const CustomChannelHeader: React.FC<{
|
|
|
214
233
|
size={48}
|
|
215
234
|
/>
|
|
216
235
|
<div className="min-w-0">
|
|
217
|
-
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
236
|
+
{onParticipantNameClick ? (
|
|
237
|
+
<button
|
|
238
|
+
type="button"
|
|
239
|
+
onClick={onParticipantNameClick}
|
|
240
|
+
aria-label={`View details for ${participantName}`}
|
|
241
|
+
className="flex min-w-0 max-w-full items-center gap-1 rounded font-medium text-black/90 transition-opacity hover:opacity-70"
|
|
242
|
+
>
|
|
243
|
+
<span className="min-w-0 truncate">{participantName}</span>
|
|
244
|
+
{headerTitleBadges && (
|
|
245
|
+
<span className="shrink-0">{headerTitleBadges}</span>
|
|
246
|
+
)}
|
|
247
|
+
<CaretRightIcon className="size-4 shrink-0" weight="bold" />
|
|
248
|
+
</button>
|
|
249
|
+
) : (
|
|
250
|
+
<h1 className="flex min-w-0 items-center gap-1 font-medium text-black/90">
|
|
251
|
+
<span className="min-w-0 truncate">{participantName}</span>
|
|
252
|
+
{headerTitleBadges && (
|
|
253
|
+
<span className="shrink-0">{headerTitleBadges}</span>
|
|
254
|
+
)}
|
|
255
|
+
</h1>
|
|
256
|
+
)}
|
|
224
257
|
{dmAgentEnabled && (
|
|
225
258
|
<div className="mt-0.5 flex items-center gap-1 text-[10px] leading-3 text-black/55">
|
|
226
259
|
<SparkleIcon className="size-3 shrink-0 text-black/55" />
|
|
@@ -306,6 +339,7 @@ const ChannelViewInner: React.FC<{
|
|
|
306
339
|
dmAgentEnabled?: boolean
|
|
307
340
|
viewerLanguage?: string
|
|
308
341
|
showChannelInfo?: boolean
|
|
342
|
+
onParticipantNameClick?: () => void
|
|
309
343
|
}> = ({
|
|
310
344
|
onBack,
|
|
311
345
|
showBackButton,
|
|
@@ -332,6 +366,7 @@ const ChannelViewInner: React.FC<{
|
|
|
332
366
|
dmAgentEnabled = false,
|
|
333
367
|
viewerLanguage,
|
|
334
368
|
showChannelInfo = true,
|
|
369
|
+
onParticipantNameClick,
|
|
335
370
|
}) => {
|
|
336
371
|
const { channel } = useChannelStateContext()
|
|
337
372
|
|
|
@@ -413,6 +448,7 @@ const ChannelViewInner: React.FC<{
|
|
|
413
448
|
onReportParticipantClick={onReportParticipantClick}
|
|
414
449
|
customChannelActions={customChannelActions}
|
|
415
450
|
renderChannelActions={renderChannelActions}
|
|
451
|
+
onParticipantNameClick={onParticipantNameClick}
|
|
416
452
|
renderHeaderTitleBadges={renderHeaderTitleBadges}
|
|
417
453
|
/>
|
|
418
454
|
</div>
|
|
@@ -492,6 +528,7 @@ export const ChannelView = React.memo<ChannelViewProps>(
|
|
|
492
528
|
attachmentPreviewList,
|
|
493
529
|
viewerLanguage,
|
|
494
530
|
showChannelInfo = true,
|
|
531
|
+
onParticipantNameClick,
|
|
495
532
|
}) => {
|
|
496
533
|
// Custom send message handler that:
|
|
497
534
|
// 1. Applies messageMetadata if provided
|
|
@@ -605,6 +642,7 @@ export const ChannelView = React.memo<ChannelViewProps>(
|
|
|
605
642
|
renderMessage={renderMessage}
|
|
606
643
|
viewerLanguage={viewerLanguage}
|
|
607
644
|
showChannelInfo={showChannelInfo}
|
|
645
|
+
onParticipantNameClick={onParticipantNameClick}
|
|
608
646
|
/>
|
|
609
647
|
</Channel>
|
|
610
648
|
</DmAgentEnabledContext.Provider>
|
package/src/index.ts
CHANGED
|
@@ -10,8 +10,6 @@ export { default as LockedAttachment } from './components/LockedAttachment'
|
|
|
10
10
|
export { default as LinkAttachment } from './components/LinkAttachment'
|
|
11
11
|
export { default as MessageAttachment } from './components/MessageAttachment'
|
|
12
12
|
export { Avatar } from './components/Avatar'
|
|
13
|
-
export { VerifiedBadge } from './components/VerifiedBadge'
|
|
14
|
-
export type { VerifiedBadgeProps } from './components/VerifiedBadge'
|
|
15
13
|
export { FaqList } from './components/FaqList'
|
|
16
14
|
export { FaqListItem } from './components/FaqList/FaqListItem'
|
|
17
15
|
export { ChannelEmptyState } from './components/MessagingShell/ChannelEmptyState'
|
|
@@ -98,14 +98,6 @@ declare module 'stream-chat' {
|
|
|
98
98
|
chatbot_paused?: boolean
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
interface CustomUserData {
|
|
102
|
-
/**
|
|
103
|
-
* Whether the user is a verified Linktree profile. When true, a
|
|
104
|
-
* verification badge is shown next to their name in messaging.
|
|
105
|
-
*/
|
|
106
|
-
is_verified?: boolean
|
|
107
|
-
}
|
|
108
|
-
|
|
109
101
|
interface CustomMessageData {
|
|
110
102
|
/**
|
|
111
103
|
* When true, hides the date timestamp in system messages.
|
package/src/types.ts
CHANGED
|
@@ -323,6 +323,17 @@ export interface ChannelViewProps {
|
|
|
323
323
|
* Use this to render staged paid or media attachments inside the input.
|
|
324
324
|
*/
|
|
325
325
|
attachmentPreviewList?: ComponentType
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Fired when the participant's name in the channel header is clicked. When
|
|
329
|
+
* provided, the name renders as a button with a trailing caret (an affordance
|
|
330
|
+
* for opening participant details / thread content); when omitted, the name
|
|
331
|
+
* renders as plain text.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* onParticipantNameClick={() => openThreadContentDialog()}
|
|
335
|
+
*/
|
|
336
|
+
onParticipantNameClick?: () => void
|
|
326
337
|
}
|
|
327
338
|
|
|
328
339
|
/**
|