@linktr.ee/messaging-react 1.38.0 → 1.40.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.
- package/dist/{Card-RgHsp9x1.js → Card-CuiPAb_A.js} +2 -2
- package/dist/{Card-RgHsp9x1.js.map → Card-CuiPAb_A.js.map} +1 -1
- package/dist/{Card-DwgUtqsA.js → Card-RBVM8Gy3.js} +2 -2
- package/dist/{Card-DwgUtqsA.js.map → Card-RBVM8Gy3.js.map} +1 -1
- package/dist/assets/index.css +1 -1
- package/dist/{index-B_4pciGp.js → index-DY-3-rt4.js} +984 -1287
- package/dist/index-DY-3-rt4.js.map +1 -0
- package/dist/index.d.ts +0 -60
- package/dist/index.js +9 -11
- package/package.json +1 -1
- package/src/components/ChannelList/ChannelList.stories.tsx +2 -7
- package/src/components/CustomMessage/MessageVoteButtons.stories.tsx +86 -0
- package/src/components/CustomMessage/MessageVoteButtons.tsx +14 -32
- package/src/components/MessagingShell/index.tsx +2 -110
- package/src/index.ts +0 -4
- package/src/styles.css +83 -7
- package/src/types.ts +0 -37
- package/dist/index-B_4pciGp.js.map +0 -1
- package/src/components/ParticipantPicker/ParticipantItem.stories.tsx +0 -190
- package/src/components/ParticipantPicker/ParticipantItem.tsx +0 -63
- package/src/components/ParticipantPicker/ParticipantPicker.stories.tsx +0 -56
- package/src/components/ParticipantPicker/ParticipantPicker.tsx +0 -229
- package/src/components/ParticipantPicker/index.tsx +0 -262
- package/src/hooks/useParticipants.ts +0 -94
package/dist/index.d.ts
CHANGED
|
@@ -58,9 +58,6 @@ export declare const ChannelList: default_2.NamedExoticComponent<ChannelListProp
|
|
|
58
58
|
export declare interface ChannelListProps {
|
|
59
59
|
onChannelSelect: (channel: Channel) => void;
|
|
60
60
|
selectedChannel?: Channel;
|
|
61
|
-
showStartConversation?: boolean;
|
|
62
|
-
onStartConversation?: () => void;
|
|
63
|
-
participantLabel?: string;
|
|
64
61
|
className?: string;
|
|
65
62
|
filters: ChannelFilters;
|
|
66
63
|
/**
|
|
@@ -363,9 +360,6 @@ declare interface MessageVoteButtonsProps {
|
|
|
363
360
|
* Messaging capabilities configuration
|
|
364
361
|
*/
|
|
365
362
|
export declare interface MessagingCapabilities {
|
|
366
|
-
showStartConversation?: boolean;
|
|
367
|
-
participantSource?: ParticipantSource;
|
|
368
|
-
participantLabel?: string;
|
|
369
363
|
/**
|
|
370
364
|
* Show the "Delete Conversation" button in channel info dialog.
|
|
371
365
|
* Defaults to true for backward compatibility.
|
|
@@ -416,7 +410,6 @@ export declare interface MessagingShellProps extends ChannelViewPassthroughProps
|
|
|
416
410
|
capabilities?: MessagingCapabilities;
|
|
417
411
|
className?: string;
|
|
418
412
|
onChannelSelect?: (channel: Channel) => void;
|
|
419
|
-
onParticipantSelect?: (participant: Participant) => void;
|
|
420
413
|
/**
|
|
421
414
|
* Auto-select a conversation with this participant on mount.
|
|
422
415
|
* Useful for deep-linking to a specific conversation (e.g., /messages/[accountUuid])
|
|
@@ -480,41 +473,6 @@ export declare interface Participant {
|
|
|
480
473
|
metadata?: Record<string, unknown>;
|
|
481
474
|
}
|
|
482
475
|
|
|
483
|
-
/**
|
|
484
|
-
* Generic participant picker component for starting conversations
|
|
485
|
-
*/
|
|
486
|
-
export declare const ParticipantPicker: default_2.FC<ParticipantPickerProps>;
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* ParticipantPicker component props
|
|
490
|
-
*/
|
|
491
|
-
export declare interface ParticipantPickerProps {
|
|
492
|
-
participantSource: ParticipantSource;
|
|
493
|
-
onSelectParticipant: (participant: Participant) => void;
|
|
494
|
-
onClose: () => void;
|
|
495
|
-
existingParticipantIds?: Set<string>;
|
|
496
|
-
participantLabel?: string;
|
|
497
|
-
searchPlaceholder?: string;
|
|
498
|
-
className?: string;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Source for loading participants (followers, team members, etc.)
|
|
503
|
-
*/
|
|
504
|
-
export declare interface ParticipantSource {
|
|
505
|
-
loadParticipants: (options?: {
|
|
506
|
-
search?: string;
|
|
507
|
-
limit?: number;
|
|
508
|
-
cursor?: string;
|
|
509
|
-
}) => Promise<{
|
|
510
|
-
participants: Participant[];
|
|
511
|
-
hasMore: boolean;
|
|
512
|
-
nextCursor?: string;
|
|
513
|
-
}>;
|
|
514
|
-
totalCount?: number;
|
|
515
|
-
loading?: boolean;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
476
|
/**
|
|
519
477
|
* Message metadata for paid messaging and chatbot flows.
|
|
520
478
|
* Used to identify message types and payment status.
|
|
@@ -548,24 +506,6 @@ declare interface UseMessageVoteResult {
|
|
|
548
506
|
*/
|
|
549
507
|
export declare const useMessaging: () => MessagingContextValue;
|
|
550
508
|
|
|
551
|
-
/**
|
|
552
|
-
* Hook for managing participant loading with search and pagination
|
|
553
|
-
*/
|
|
554
|
-
export declare const useParticipants: (participantSource: ParticipantSource, options?: {
|
|
555
|
-
initialSearch?: string;
|
|
556
|
-
pageSize?: number;
|
|
557
|
-
}) => {
|
|
558
|
-
participants: Participant[];
|
|
559
|
-
loading: boolean;
|
|
560
|
-
error: string | null;
|
|
561
|
-
searchQuery: string;
|
|
562
|
-
hasMore: boolean;
|
|
563
|
-
totalCount: number | undefined;
|
|
564
|
-
loadMore: () => void;
|
|
565
|
-
search: (query: string) => void;
|
|
566
|
-
refresh: () => void;
|
|
567
|
-
};
|
|
568
|
-
|
|
569
509
|
export declare interface VisitorCardProps extends LockedAttachmentBaseProps {
|
|
570
510
|
/**
|
|
571
511
|
* Called when the visitor clicks Unlock on an unpaid attachment.
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
import { b as
|
|
1
|
+
import { b as a, c as t, C as i, d as n, e as o, f as g, F as r, g as M, L as m, M as l, h as u, i as h, j as d, k as v, r as C, l as L, u as c, m as A, n as F } from "./index-DY-3-rt4.js";
|
|
2
2
|
export {
|
|
3
|
-
|
|
3
|
+
a as ActionButton,
|
|
4
4
|
t as Avatar,
|
|
5
5
|
i as ChannelEmptyState,
|
|
6
6
|
n as ChannelList,
|
|
7
7
|
o as ChannelView,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
g as CustomMessageProvider,
|
|
9
|
+
r as FaqList,
|
|
10
10
|
M as FaqListItem,
|
|
11
11
|
m as LockedAttachment,
|
|
12
12
|
l as MediaMessage,
|
|
13
13
|
u as MessageVoteButtons,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
d as ParticipantPicker,
|
|
14
|
+
h as MessagingProvider,
|
|
15
|
+
d as MessagingShell,
|
|
17
16
|
v as formatRelativeTime,
|
|
18
17
|
C as resolveLinkAttachment,
|
|
19
18
|
L as resolveMediaFromMessage,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
A as useParticipants
|
|
19
|
+
c as useCustomMessage,
|
|
20
|
+
A as useMessageVote,
|
|
21
|
+
F as useMessaging
|
|
24
22
|
};
|
|
25
23
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -35,16 +35,11 @@ const Template: StoryFn<ComponentProps> = (args) => {
|
|
|
35
35
|
export const Default: StoryFn<ComponentProps> = Template.bind({})
|
|
36
36
|
Default.args = {
|
|
37
37
|
onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
|
|
38
|
-
participantLabel: 'participants',
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
export const
|
|
42
|
-
|
|
40
|
+
export const WithSelection: StoryFn<ComponentProps> = Template.bind({})
|
|
41
|
+
WithSelection.args = {
|
|
43
42
|
onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
|
|
44
|
-
showStartConversation: true,
|
|
45
|
-
onStartConversation: () => console.log('Start conversation clicked'),
|
|
46
|
-
participantLabel: 'followers',
|
|
47
43
|
}
|
|
48
44
|
|
|
49
45
|
|
|
50
|
-
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Meta, StoryFn } from '@storybook/react'
|
|
2
|
+
import React, { useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import type { VoteSelection } from '../../hooks/useMessageVote'
|
|
5
|
+
|
|
6
|
+
import { MessageVoteButtons } from './MessageVoteButtons'
|
|
7
|
+
|
|
8
|
+
type ComponentProps = React.ComponentProps<typeof MessageVoteButtons>
|
|
9
|
+
|
|
10
|
+
const meta: Meta<ComponentProps> = {
|
|
11
|
+
title: 'MessageVoteButtons',
|
|
12
|
+
component: MessageVoteButtons,
|
|
13
|
+
parameters: {
|
|
14
|
+
layout: 'centered',
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
export default meta
|
|
18
|
+
|
|
19
|
+
const Template: StoryFn<ComponentProps> = (args) => (
|
|
20
|
+
<div className="p-12">
|
|
21
|
+
<MessageVoteButtons {...args} />
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
export const Unselected: StoryFn<ComponentProps> = Template.bind({})
|
|
26
|
+
Unselected.args = {
|
|
27
|
+
selected: null,
|
|
28
|
+
onVoteUp: () => {},
|
|
29
|
+
onVoteDown: () => {},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const GoodResponse: StoryFn<ComponentProps> = Template.bind({})
|
|
33
|
+
GoodResponse.args = {
|
|
34
|
+
selected: 'up',
|
|
35
|
+
onVoteUp: () => {},
|
|
36
|
+
onVoteDown: () => {},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const BadResponse: StoryFn<ComponentProps> = Template.bind({})
|
|
40
|
+
BadResponse.args = {
|
|
41
|
+
selected: 'down',
|
|
42
|
+
onVoteUp: () => {},
|
|
43
|
+
onVoteDown: () => {},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const Interactive: StoryFn = () => {
|
|
47
|
+
const [selected, setSelected] = useState<VoteSelection>(null)
|
|
48
|
+
return (
|
|
49
|
+
<div className="p-12">
|
|
50
|
+
<MessageVoteButtons
|
|
51
|
+
selected={selected}
|
|
52
|
+
onVoteUp={() => setSelected(selected === 'up' ? null : 'up')}
|
|
53
|
+
onVoteDown={() => setSelected(selected === 'down' ? null : 'down')}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const AllVariants: StoryFn = () => (
|
|
60
|
+
<div className="p-12 flex flex-col gap-6">
|
|
61
|
+
<div className="flex items-center gap-4">
|
|
62
|
+
<span className="text-sm w-32">Unselected:</span>
|
|
63
|
+
<MessageVoteButtons
|
|
64
|
+
selected={null}
|
|
65
|
+
onVoteUp={() => {}}
|
|
66
|
+
onVoteDown={() => {}}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
<div className="flex items-center gap-4">
|
|
70
|
+
<span className="text-sm w-32">Good response:</span>
|
|
71
|
+
<MessageVoteButtons
|
|
72
|
+
selected="up"
|
|
73
|
+
onVoteUp={() => {}}
|
|
74
|
+
onVoteDown={() => {}}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
<div className="flex items-center gap-4">
|
|
78
|
+
<span className="text-sm w-32">Bad response:</span>
|
|
79
|
+
<MessageVoteButtons
|
|
80
|
+
selected="down"
|
|
81
|
+
onVoteUp={() => {}}
|
|
82
|
+
onVoteDown={() => {}}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ThumbsUpIcon, ThumbsDownIcon } from '@phosphor-icons/react'
|
|
2
|
+
import classNames from 'classnames'
|
|
1
3
|
import React from 'react'
|
|
2
4
|
|
|
3
5
|
import type { VoteSelection } from '../../hooks/useMessageVote'
|
|
@@ -8,32 +10,6 @@ interface MessageVoteButtonsProps {
|
|
|
8
10
|
onVoteDown: () => void
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
const ThumbUpIcon: React.FC<{ filled: boolean }> = ({ filled }) => (
|
|
12
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
13
|
-
<path
|
|
14
|
-
d="M4.667 7.333l2.666-6A1.333 1.333 0 018.667 2v2.667a.667.667 0 00.666.666h3.764a1.334 1.334 0 011.192 1.93l-2.333 4.666a1.333 1.333 0 01-1.193.738H4.667m0-5.334v5.334m0-5.334H2.667a1.333 1.333 0 00-1.334 1.334v2.666a1.333 1.333 0 001.334 1.334h2"
|
|
15
|
-
stroke="currentColor"
|
|
16
|
-
strokeWidth="1.33"
|
|
17
|
-
strokeLinecap="round"
|
|
18
|
-
strokeLinejoin="round"
|
|
19
|
-
fill={filled ? 'currentColor' : 'none'}
|
|
20
|
-
/>
|
|
21
|
-
</svg>
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
const ThumbDownIcon: React.FC<{ filled: boolean }> = ({ filled }) => (
|
|
25
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
26
|
-
<path
|
|
27
|
-
d="M11.333 8.667l-2.666 6A1.333 1.333 0 017.333 14v-2.667a.667.667 0 00-.666-.666H2.903a1.334 1.334 0 01-1.192-1.93l2.333-4.666a1.333 1.333 0 011.193-.738h6.096m0 5.334V3.333m0 5.334h2a1.333 1.333 0 001.334-1.334V4.667a1.333 1.333 0 00-1.334-1.334h-2"
|
|
28
|
-
stroke="currentColor"
|
|
29
|
-
strokeWidth="1.33"
|
|
30
|
-
strokeLinecap="round"
|
|
31
|
-
strokeLinejoin="round"
|
|
32
|
-
fill={filled ? 'currentColor' : 'none'}
|
|
33
|
-
/>
|
|
34
|
-
</svg>
|
|
35
|
-
)
|
|
36
|
-
|
|
37
13
|
export const MessageVoteButtons: React.FC<MessageVoteButtonsProps> = ({
|
|
38
14
|
selected,
|
|
39
15
|
onVoteUp,
|
|
@@ -42,21 +18,27 @@ export const MessageVoteButtons: React.FC<MessageVoteButtonsProps> = ({
|
|
|
42
18
|
<div className="message-vote-buttons">
|
|
43
19
|
<button
|
|
44
20
|
type="button"
|
|
45
|
-
className={
|
|
21
|
+
className={classNames('message-vote-button focus-ring', {
|
|
22
|
+
'message-vote-button--selected': selected === 'up',
|
|
23
|
+
})}
|
|
46
24
|
onClick={onVoteUp}
|
|
47
|
-
aria-label="
|
|
25
|
+
aria-label="Good response"
|
|
48
26
|
aria-pressed={selected === 'up'}
|
|
27
|
+
data-tooltip="Good response"
|
|
49
28
|
>
|
|
50
|
-
<
|
|
29
|
+
<ThumbsUpIcon size={16} weight={selected === 'up' ? 'fill' : 'regular'} />
|
|
51
30
|
</button>
|
|
52
31
|
<button
|
|
53
32
|
type="button"
|
|
54
|
-
className={
|
|
33
|
+
className={classNames('message-vote-button focus-ring', {
|
|
34
|
+
'message-vote-button--selected': selected === 'down',
|
|
35
|
+
})}
|
|
55
36
|
onClick={onVoteDown}
|
|
56
|
-
aria-label="
|
|
37
|
+
aria-label="Bad response"
|
|
57
38
|
aria-pressed={selected === 'down'}
|
|
39
|
+
data-tooltip="Bad response"
|
|
58
40
|
>
|
|
59
|
-
<
|
|
41
|
+
<ThumbsDownIcon size={16} weight={selected === 'down' ? 'fill' : 'regular'} />
|
|
60
42
|
</button>
|
|
61
43
|
</div>
|
|
62
44
|
)
|
|
@@ -3,10 +3,9 @@ import React, { useState, useCallback, useRef, useEffect } from 'react'
|
|
|
3
3
|
import type { Channel } from 'stream-chat'
|
|
4
4
|
|
|
5
5
|
import { useMessaging } from '../../hooks/useMessaging'
|
|
6
|
-
import type { MessagingShellProps
|
|
6
|
+
import type { MessagingShellProps } from '../../types'
|
|
7
7
|
import { ChannelList } from '../ChannelList'
|
|
8
8
|
import { ChannelView } from '../ChannelView'
|
|
9
|
-
import { ParticipantPicker } from '../ParticipantPicker'
|
|
10
9
|
|
|
11
10
|
import { EmptyState } from './EmptyState'
|
|
12
11
|
import { ErrorState } from './ErrorState'
|
|
@@ -21,7 +20,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
21
20
|
renderMessageInputActions,
|
|
22
21
|
renderConversationFooter,
|
|
23
22
|
onChannelSelect,
|
|
24
|
-
onParticipantSelect,
|
|
25
23
|
initialParticipantFilter,
|
|
26
24
|
initialParticipantData,
|
|
27
25
|
CustomChannelEmptyState,
|
|
@@ -57,21 +55,12 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
57
55
|
const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null)
|
|
58
56
|
const [hasChannels, setHasChannels] = useState(false)
|
|
59
57
|
const [channelsLoaded, setChannelsLoaded] = useState(false)
|
|
60
|
-
const [_showParticipantPicker, setShowParticipantPicker] = useState(false)
|
|
61
|
-
const [existingParticipantIds, setExistingParticipantIds] = useState<
|
|
62
|
-
Set<string>
|
|
63
|
-
>(new Set())
|
|
64
|
-
const [pickerKey, _setPickerKey] = useState(0) // Key to force remount of ParticipantPicker
|
|
65
58
|
const [directConversationMode, setDirectConversationMode] = useState(false)
|
|
66
59
|
const [directConversationError, setDirectConversationError] = useState<
|
|
67
60
|
string | null
|
|
68
61
|
>(null)
|
|
69
62
|
|
|
70
|
-
const participantPickerRef = useRef<HTMLDialogElement>(null)
|
|
71
|
-
|
|
72
63
|
const {
|
|
73
|
-
participantSource,
|
|
74
|
-
participantLabel = 'participants',
|
|
75
64
|
showDeleteConversation = true,
|
|
76
65
|
} = capabilities
|
|
77
66
|
|
|
@@ -121,27 +110,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
121
110
|
{ limit: 100 }
|
|
122
111
|
)
|
|
123
112
|
|
|
124
|
-
const memberIds = new Set<string>()
|
|
125
|
-
channels.forEach((channel: Channel) => {
|
|
126
|
-
const members = channel.state.members
|
|
127
|
-
Object.values(members).forEach((member) => {
|
|
128
|
-
const memberId = member.user?.id
|
|
129
|
-
if (memberId && memberId !== userId) {
|
|
130
|
-
memberIds.add(memberId)
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
// Only update if the set contents have changed to prevent re-renders
|
|
136
|
-
setExistingParticipantIds((prev) => {
|
|
137
|
-
if (
|
|
138
|
-
prev.size === memberIds.size &&
|
|
139
|
-
[...prev].every((id) => memberIds.has(id))
|
|
140
|
-
) {
|
|
141
|
-
return prev
|
|
142
|
-
}
|
|
143
|
-
return memberIds
|
|
144
|
-
})
|
|
145
113
|
setHasChannels(channels.length > 0)
|
|
146
114
|
setChannelsLoaded(true)
|
|
147
115
|
syncedRef.current = userId // Mark as synced for this user
|
|
@@ -149,7 +117,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
149
117
|
if (debug) {
|
|
150
118
|
console.log('[MessagingShell] Channels synced successfully:', {
|
|
151
119
|
channelCount: channels.length,
|
|
152
|
-
memberCount: memberIds.size,
|
|
153
120
|
})
|
|
154
121
|
}
|
|
155
122
|
} catch (error) {
|
|
@@ -158,7 +125,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
158
125
|
}
|
|
159
126
|
}, [client, isConnected, debug])
|
|
160
127
|
|
|
161
|
-
// Sync existing channels to
|
|
128
|
+
// Sync existing channels to drive empty-state behavior.
|
|
162
129
|
useEffect(() => {
|
|
163
130
|
if (!client || !isConnected) return
|
|
164
131
|
|
|
@@ -303,58 +270,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
303
270
|
setSelectedChannel(null)
|
|
304
271
|
}, [directConversationMode])
|
|
305
272
|
|
|
306
|
-
const handleSelectParticipant = useCallback(
|
|
307
|
-
async (participant: Participant) => {
|
|
308
|
-
if (!service) return
|
|
309
|
-
|
|
310
|
-
try {
|
|
311
|
-
if (debug) {
|
|
312
|
-
console.log(
|
|
313
|
-
'[MessagingShell] Starting conversation with:',
|
|
314
|
-
participant.id
|
|
315
|
-
)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const channel = await service.startChannelWithParticipant({
|
|
319
|
-
id: participant.id,
|
|
320
|
-
name: participant.name,
|
|
321
|
-
email: participant.email,
|
|
322
|
-
phone: participant.phone,
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
// Show the channel
|
|
326
|
-
try {
|
|
327
|
-
await channel.show()
|
|
328
|
-
} catch (error) {
|
|
329
|
-
console.warn('[MessagingShell] Failed to unhide channel:', error)
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
setSelectedChannel(channel)
|
|
333
|
-
setShowParticipantPicker(false)
|
|
334
|
-
participantPickerRef.current?.close()
|
|
335
|
-
|
|
336
|
-
onParticipantSelect?.(participant)
|
|
337
|
-
} catch (error) {
|
|
338
|
-
console.error('[MessagingShell] Failed to start conversation:', error)
|
|
339
|
-
}
|
|
340
|
-
},
|
|
341
|
-
[service, onParticipantSelect, debug]
|
|
342
|
-
)
|
|
343
|
-
|
|
344
|
-
const handleCloseParticipantPicker = useCallback(() => {
|
|
345
|
-
setShowParticipantPicker(false)
|
|
346
|
-
participantPickerRef.current?.close()
|
|
347
|
-
}, [])
|
|
348
|
-
|
|
349
|
-
const handleDialogBackdropClick = useCallback(
|
|
350
|
-
(e: React.MouseEvent<HTMLDialogElement>) => {
|
|
351
|
-
if (e.target === participantPickerRef.current) {
|
|
352
|
-
handleCloseParticipantPicker()
|
|
353
|
-
}
|
|
354
|
-
},
|
|
355
|
-
[handleCloseParticipantPicker]
|
|
356
|
-
)
|
|
357
|
-
|
|
358
273
|
const handleLeaveConversation = useCallback(
|
|
359
274
|
async (channel: Channel) => {
|
|
360
275
|
if (debug) {
|
|
@@ -520,29 +435,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
520
435
|
)}
|
|
521
436
|
</div>
|
|
522
437
|
</div>
|
|
523
|
-
|
|
524
|
-
{/* Participant Picker Dialog */}
|
|
525
|
-
{participantSource && (
|
|
526
|
-
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
|
|
527
|
-
<dialog
|
|
528
|
-
ref={participantPickerRef}
|
|
529
|
-
className="mes-dialog"
|
|
530
|
-
onClick={handleDialogBackdropClick}
|
|
531
|
-
onClose={handleCloseParticipantPicker}
|
|
532
|
-
>
|
|
533
|
-
<div className="h-full w-full bg-white shadow-max-elevation-light">
|
|
534
|
-
<ParticipantPicker
|
|
535
|
-
key={pickerKey}
|
|
536
|
-
participantSource={participantSource}
|
|
537
|
-
onSelectParticipant={handleSelectParticipant}
|
|
538
|
-
onClose={handleCloseParticipantPicker}
|
|
539
|
-
existingParticipantIds={existingParticipantIds}
|
|
540
|
-
participantLabel={participantLabel}
|
|
541
|
-
searchPlaceholder={`Search ${participantLabel}...`}
|
|
542
|
-
/>
|
|
543
|
-
</div>
|
|
544
|
-
</dialog>
|
|
545
|
-
)}
|
|
546
438
|
</div>
|
|
547
439
|
)
|
|
548
440
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export { ChannelList } from './components/ChannelList'
|
|
|
7
7
|
export { ChannelView } from './components/ChannelView'
|
|
8
8
|
export { default as ActionButton } from './components/ActionButton'
|
|
9
9
|
export { default as LockedAttachment } from './components/LockedAttachment'
|
|
10
|
-
export { ParticipantPicker } from './components/ParticipantPicker'
|
|
11
10
|
export { Avatar } from './components/Avatar'
|
|
12
11
|
export { FaqList } from './components/FaqList'
|
|
13
12
|
export { FaqListItem } from './components/FaqList/FaqListItem'
|
|
@@ -26,7 +25,6 @@ export { CustomMessageProvider } from './components/CustomMessage/context'
|
|
|
26
25
|
|
|
27
26
|
// Hooks
|
|
28
27
|
export { useMessaging } from './hooks/useMessaging'
|
|
29
|
-
export { useParticipants } from './hooks/useParticipants'
|
|
30
28
|
export { useMessageVote } from './hooks/useMessageVote'
|
|
31
29
|
export { useCustomMessage } from './components/CustomMessage/context'
|
|
32
30
|
|
|
@@ -38,10 +36,8 @@ export type {
|
|
|
38
36
|
MessagingShellProps,
|
|
39
37
|
ChannelListProps,
|
|
40
38
|
ChannelViewProps,
|
|
41
|
-
ParticipantPickerProps,
|
|
42
39
|
MessagingProviderProps,
|
|
43
40
|
MessagingCapabilities,
|
|
44
|
-
ParticipantSource,
|
|
45
41
|
Participant,
|
|
46
42
|
LockedAttachmentSource,
|
|
47
43
|
} from './types'
|
package/src/styles.css
CHANGED
|
@@ -280,6 +280,7 @@
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
.message-vote-button {
|
|
283
|
+
position: relative;
|
|
283
284
|
display: flex;
|
|
284
285
|
align-items: center;
|
|
285
286
|
justify-content: center;
|
|
@@ -289,7 +290,7 @@
|
|
|
289
290
|
border: none;
|
|
290
291
|
border-radius: 50%;
|
|
291
292
|
background-color: transparent;
|
|
292
|
-
color:
|
|
293
|
+
color: #737373;
|
|
293
294
|
cursor: pointer;
|
|
294
295
|
transition:
|
|
295
296
|
background-color 0.15s,
|
|
@@ -297,16 +298,91 @@
|
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
.message-vote-button:hover {
|
|
300
|
-
background-color: rgba(0, 0, 0, 0.
|
|
301
|
-
color:
|
|
301
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
302
|
+
color: #737373;
|
|
302
303
|
}
|
|
303
304
|
|
|
304
|
-
.message-vote-button
|
|
305
|
-
|
|
305
|
+
.message-vote-button[data-tooltip]::after {
|
|
306
|
+
content: attr(data-tooltip);
|
|
307
|
+
position: absolute;
|
|
308
|
+
bottom: calc(100% + 6px);
|
|
309
|
+
left: 50%;
|
|
310
|
+
transform: translateX(-50%);
|
|
311
|
+
background-color: rgba(0, 0, 0, 0.85);
|
|
312
|
+
color: #fff;
|
|
313
|
+
font-size: 12px;
|
|
314
|
+
line-height: 1;
|
|
315
|
+
padding: 4px 8px;
|
|
316
|
+
border-radius: 4px;
|
|
317
|
+
white-space: nowrap;
|
|
318
|
+
pointer-events: none;
|
|
319
|
+
opacity: 0;
|
|
320
|
+
transition: opacity 0.15s 0s;
|
|
306
321
|
}
|
|
307
322
|
|
|
308
|
-
.message-vote-button
|
|
309
|
-
|
|
323
|
+
.message-vote-button[data-tooltip]:hover::after,
|
|
324
|
+
.message-vote-button[data-tooltip]:focus-visible::after {
|
|
325
|
+
opacity: 1;
|
|
326
|
+
transition-delay: 300ms;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* Chatbot reply markdown — restore semantics that consumer Tailwind preflight
|
|
330
|
+
(or other resets) strip from the body of `.str-chat__message-text-inner`. */
|
|
331
|
+
.str-chat__message-text-inner :where(h1, h2, h3, h4, h5, h6) {
|
|
332
|
+
font-weight: 600;
|
|
333
|
+
margin: 0.5rem 0 0.25rem;
|
|
334
|
+
line-height: 1.3;
|
|
335
|
+
text-wrap: balance;
|
|
336
|
+
}
|
|
337
|
+
.str-chat__message-text-inner h1 {
|
|
338
|
+
font-size: 1.5rem;
|
|
339
|
+
}
|
|
340
|
+
.str-chat__message-text-inner h2 {
|
|
341
|
+
font-size: 1.25rem;
|
|
342
|
+
}
|
|
343
|
+
.str-chat__message-text-inner h3 {
|
|
344
|
+
font-size: 1.0625rem;
|
|
345
|
+
}
|
|
346
|
+
.str-chat__message-text-inner :where(h1, h2, h3, h4, h5, h6):first-child {
|
|
347
|
+
margin-top: 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.str-chat__message-text-inner ul {
|
|
351
|
+
list-style-type: disc;
|
|
352
|
+
padding-inline-start: 1.25rem;
|
|
353
|
+
margin: 0.25rem 0;
|
|
354
|
+
}
|
|
355
|
+
.str-chat__message-text-inner ol {
|
|
356
|
+
list-style-type: decimal;
|
|
357
|
+
padding-inline-start: 1.25rem;
|
|
358
|
+
margin: 0.25rem 0;
|
|
359
|
+
}
|
|
360
|
+
.str-chat__message-text-inner li {
|
|
361
|
+
display: list-item;
|
|
362
|
+
margin: 0.125rem 0;
|
|
363
|
+
}
|
|
364
|
+
.str-chat__message-text-inner ul ul,
|
|
365
|
+
.str-chat__message-text-inner ol ol,
|
|
366
|
+
.str-chat__message-text-inner ul ol,
|
|
367
|
+
.str-chat__message-text-inner ol ul {
|
|
368
|
+
margin: 0;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.str-chat__message-text-inner a {
|
|
372
|
+
text-decoration: underline;
|
|
373
|
+
text-underline-offset: 0.15em;
|
|
374
|
+
word-break: break-word;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.str-chat__message-text-inner p {
|
|
378
|
+
margin: 0.25rem 0;
|
|
379
|
+
text-wrap: pretty;
|
|
380
|
+
}
|
|
381
|
+
.str-chat__message-text-inner > :first-child {
|
|
382
|
+
margin-top: 0;
|
|
383
|
+
}
|
|
384
|
+
.str-chat__message-text-inner > :last-child {
|
|
385
|
+
margin-bottom: 0;
|
|
310
386
|
}
|
|
311
387
|
|
|
312
388
|
/* Standalone tip message (tip without text) */
|