@linktr.ee/messaging-react 1.7.2 → 1.8.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 (69) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/assets/index.css +1 -1
  3. package/dist/components/ActionButton/ActionButton.test.d.ts +2 -0
  4. package/dist/components/ActionButton/ActionButton.test.d.ts.map +1 -0
  5. package/dist/components/ActionButton/index.d.ts +7 -0
  6. package/dist/components/ActionButton/index.d.ts.map +1 -0
  7. package/dist/components/Avatar/getAvatarEmoji.d.ts +7 -0
  8. package/dist/components/Avatar/getAvatarEmoji.d.ts.map +1 -0
  9. package/dist/components/Avatar/index.d.ts +13 -0
  10. package/dist/components/Avatar/index.d.ts.map +1 -0
  11. package/dist/components/ChannelList/CustomChannelPreview.d.ts +13 -0
  12. package/dist/components/ChannelList/CustomChannelPreview.d.ts.map +1 -0
  13. package/dist/components/ChannelList/index.d.ts +7 -0
  14. package/dist/components/ChannelList/index.d.ts.map +1 -0
  15. package/dist/components/ChannelView.d.ts +7 -0
  16. package/dist/components/ChannelView.d.ts.map +1 -0
  17. package/dist/components/CloseButton/index.d.ts +6 -0
  18. package/dist/components/CloseButton/index.d.ts.map +1 -0
  19. package/dist/components/FaqList/FaqListItem.d.ts +9 -0
  20. package/dist/components/FaqList/FaqListItem.d.ts.map +1 -0
  21. package/dist/components/FaqList/index.d.ts +19 -0
  22. package/dist/components/FaqList/index.d.ts.map +1 -0
  23. package/dist/components/IconButton/index.d.ts +9 -0
  24. package/dist/components/IconButton/index.d.ts.map +1 -0
  25. package/dist/components/Loading/index.d.ts +7 -0
  26. package/dist/components/Loading/index.d.ts.map +1 -0
  27. package/dist/components/MessagingShell/ChannelEmptyState.d.ts +6 -0
  28. package/dist/components/MessagingShell/ChannelEmptyState.d.ts.map +1 -0
  29. package/dist/components/MessagingShell/EmptyState.d.ts +10 -0
  30. package/dist/components/MessagingShell/EmptyState.d.ts.map +1 -0
  31. package/dist/components/MessagingShell/ErrorState.d.ts +9 -0
  32. package/dist/components/MessagingShell/ErrorState.d.ts.map +1 -0
  33. package/dist/components/MessagingShell/LoadingState.d.ts +5 -0
  34. package/dist/components/MessagingShell/LoadingState.d.ts.map +1 -0
  35. package/dist/components/MessagingShell/index.d.ts +7 -0
  36. package/dist/components/MessagingShell/index.d.ts.map +1 -0
  37. package/dist/components/ParticipantPicker/ParticipantItem.d.ts +13 -0
  38. package/dist/components/ParticipantPicker/ParticipantItem.d.ts.map +1 -0
  39. package/dist/components/ParticipantPicker/ParticipantPicker.d.ts +7 -0
  40. package/dist/components/ParticipantPicker/ParticipantPicker.d.ts.map +1 -0
  41. package/dist/components/ParticipantPicker/index.d.ts +7 -0
  42. package/dist/components/ParticipantPicker/index.d.ts.map +1 -0
  43. package/dist/components/SearchInput/SearchInput.test.d.ts +2 -0
  44. package/dist/components/SearchInput/SearchInput.test.d.ts.map +1 -0
  45. package/dist/components/SearchInput/index.d.ts +8 -0
  46. package/dist/components/SearchInput/index.d.ts.map +1 -0
  47. package/dist/hooks/useMessaging.d.ts +6 -0
  48. package/dist/hooks/useMessaging.d.ts.map +1 -0
  49. package/dist/hooks/useParticipants.d.ts +19 -0
  50. package/dist/hooks/useParticipants.d.ts.map +1 -0
  51. package/dist/index.d.ts +17 -258
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +607 -755
  54. package/dist/index.js.map +1 -1
  55. package/dist/providers/MessagingProvider.d.ts +27 -0
  56. package/dist/providers/MessagingProvider.d.ts.map +1 -0
  57. package/dist/stories/mocks.d.ts +29 -0
  58. package/dist/stories/mocks.d.ts.map +1 -0
  59. package/dist/test/setup.d.ts +2 -0
  60. package/dist/test/setup.d.ts.map +1 -0
  61. package/dist/test/utils.d.ts +12 -0
  62. package/dist/test/utils.d.ts.map +1 -0
  63. package/dist/types.d.ts +138 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/package.json +1 -1
  66. package/src/components/ChannelList/index.tsx +5 -108
  67. package/src/components/FaqList/FaqListItem.tsx +0 -1
  68. package/src/components/MessagingShell/index.tsx +24 -5
  69. package/src/types.ts +7 -2
@@ -0,0 +1,27 @@
1
+ import { StreamChatService } from '@linktr.ee/messaging-core';
2
+ import React from 'react';
3
+ import type { StreamChat } from 'stream-chat';
4
+ import type { MessagingProviderProps, MessagingCapabilities, MessagingCustomization } from '../types';
5
+ /**
6
+ * Context value for messaging state and service
7
+ */
8
+ export interface MessagingContextValue {
9
+ service: StreamChatService | null;
10
+ client: StreamChat | null;
11
+ isConnected: boolean;
12
+ isLoading: boolean;
13
+ error: string | null;
14
+ capabilities: MessagingCapabilities;
15
+ customization: MessagingCustomization;
16
+ refreshConnection: () => Promise<void>;
17
+ debug: boolean;
18
+ }
19
+ /**
20
+ * Hook to access messaging context
21
+ */
22
+ export declare const useMessagingContext: () => MessagingContextValue;
23
+ /**
24
+ * Provider component that wraps messaging-core with React state management
25
+ */
26
+ export declare const MessagingProvider: React.FC<MessagingProviderProps>;
27
+ //# sourceMappingURL=MessagingProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagingProvider.d.ts","sourceRoot":"","sources":["../../src/providers/MessagingProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAON,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,UAAU,CAAA;AAEjB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACjC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,YAAY,EAAE,qBAAqB,CAAA;IACnC,aAAa,EAAE,sBAAsB,CAAA;IACrC,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,KAAK,EAAE,OAAO,CAAA;CACf;AAcD;;GAEG;AACH,eAAO,MAAM,mBAAmB,6BAAqC,CAAA;AAErE;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAkT9D,CAAA"}
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ export declare const MockChatProvider: React.FC<{
3
+ children: React.ReactNode;
4
+ }>;
5
+ export declare const MockChatProviderWithChannels: React.FC<{
6
+ children: React.ReactNode;
7
+ channelCount?: number;
8
+ }>;
9
+ export declare const mockParticipants: {
10
+ id: string;
11
+ name: string;
12
+ email: string;
13
+ image: string;
14
+ }[];
15
+ export declare const mockParticipantSource: {
16
+ loadParticipants: (options?: {
17
+ search?: string;
18
+ limit?: number;
19
+ }) => Promise<{
20
+ participants: {
21
+ id: string;
22
+ name: string;
23
+ email: string;
24
+ image: string;
25
+ }[];
26
+ hasMore: boolean;
27
+ }>;
28
+ };
29
+ //# sourceMappingURL=mocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../../src/stories/mocks.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AA+BzB,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAYpE,CAAA;AAGD,eAAO,MAAM,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC;IAClD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAwDA,CAAA;AAGD,eAAO,MAAM,gBAAgB;;;;;GA+B5B,CAAA;AAGD,eAAO,MAAM,qBAAqB;iCACG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;CAYvE,CAAA"}
@@ -0,0 +1,2 @@
1
+ import '@testing-library/jest-dom/vitest';
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { RenderOptions, RenderResult } from '@testing-library/react';
2
+ import { ReactElement } from 'react';
3
+ /**
4
+ * Custom render function that wraps components with common providers
5
+ */
6
+ export declare function renderWithProviders(ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>): RenderResult;
7
+ /**
8
+ * Re-export everything from React Testing Library
9
+ */
10
+ export * from '@testing-library/react';
11
+ export { default as userEvent } from '@testing-library/user-event';
12
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAa,MAAM,OAAO,CAAA;AAE/C;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,YAAY,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GACvC,YAAY,CAMd;AAED;;GAEG;AACH,cAAc,wBAAwB,CAAA;AACtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAA"}
@@ -0,0 +1,138 @@
1
+ import type { MessagingUser, StreamChatServiceConfig } from '@linktr.ee/messaging-core';
2
+ import type { Channel, ChannelFilters } from 'stream-chat';
3
+ /**
4
+ * Generic participant interface for different host environments
5
+ */
6
+ export interface Participant {
7
+ id: string;
8
+ name: string;
9
+ email?: string;
10
+ image?: string;
11
+ username?: string;
12
+ phone?: string;
13
+ metadata?: Record<string, unknown>;
14
+ }
15
+ /**
16
+ * Source for loading participants (followers, team members, etc.)
17
+ */
18
+ export interface ParticipantSource {
19
+ loadParticipants: (options?: {
20
+ search?: string;
21
+ limit?: number;
22
+ cursor?: string;
23
+ }) => Promise<{
24
+ participants: Participant[];
25
+ hasMore: boolean;
26
+ nextCursor?: string;
27
+ }>;
28
+ totalCount?: number;
29
+ loading?: boolean;
30
+ }
31
+ /**
32
+ * Messaging capabilities configuration
33
+ */
34
+ export interface MessagingCapabilities {
35
+ showStartConversation?: boolean;
36
+ participantSource?: ParticipantSource;
37
+ participantLabel?: string;
38
+ }
39
+ /**
40
+ * Customization options
41
+ */
42
+ export interface MessagingCustomization {
43
+ theme?: 'light' | 'dark' | 'auto';
44
+ accentColor?: string;
45
+ }
46
+ /**
47
+ * Main MessagingShell component props
48
+ */
49
+ export interface MessagingShellProps {
50
+ capabilities?: MessagingCapabilities;
51
+ customization?: MessagingCustomization;
52
+ className?: string;
53
+ renderMessageInputActions?: (channel: Channel) => React.ReactNode;
54
+ onChannelSelect?: (channel: Channel) => void;
55
+ onParticipantSelect?: (participant: Participant) => void;
56
+ /**
57
+ * Auto-select a conversation with this participant on mount.
58
+ * Useful for deep-linking to a specific conversation (e.g., /messages/[accountUuid])
59
+ *
60
+ * If a channel with this participant exists, it will be auto-selected.
61
+ * If no channel exists, you can provide initialParticipantData to automatically
62
+ * create the channel using the existing ChannelCreator.
63
+ */
64
+ initialParticipantFilter?: string;
65
+ /**
66
+ * Participant data for auto-creating a channel when initialParticipantFilter
67
+ * is provided but no channel exists. If this is provided, MessagingShell will
68
+ * automatically call service.startChannelWithParticipant() to create the channel.
69
+ *
70
+ * This reuses the existing ChannelCreator from StreamChatServiceConfig.
71
+ */
72
+ initialParticipantData?: Participant;
73
+ /**
74
+ * Custom empty state component to render when a channel has no messages.
75
+ * Useful for showing FAQs or other contextual information in empty channels.
76
+ */
77
+ CustomChannelEmptyState?: React.ComponentType;
78
+ /**
79
+ * Controls whether the channel list is shown. When false, the channel list
80
+ * is immediately hidden. Useful for direct conversation mode where you want
81
+ * to show only the channel view without the list.
82
+ */
83
+ showChannelList?: boolean;
84
+ /**
85
+ * Filters for channel list. Passed through to StreamChat ChannelList.
86
+ */
87
+ filters?: ChannelFilters;
88
+ }
89
+ /**
90
+ * ChannelList component props
91
+ */
92
+ export interface ChannelListProps {
93
+ onChannelSelect: (channel: Channel) => void;
94
+ selectedChannel?: Channel;
95
+ showStartConversation?: boolean;
96
+ onStartConversation?: () => void;
97
+ participantLabel?: string;
98
+ className?: string;
99
+ filters: ChannelFilters;
100
+ }
101
+ /**
102
+ * ChannelView component props
103
+ */
104
+ export interface ChannelViewProps {
105
+ channel: Channel;
106
+ onBack?: () => void;
107
+ showBackButton?: boolean;
108
+ renderMessageInputActions?: (channel: Channel) => React.ReactNode;
109
+ onLeaveConversation?: (channel: Channel) => void;
110
+ onBlockParticipant?: (participantId?: string) => void;
111
+ className?: string;
112
+ CustomChannelEmptyState?: React.ComponentType;
113
+ }
114
+ /**
115
+ * ParticipantPicker component props
116
+ */
117
+ export interface ParticipantPickerProps {
118
+ participantSource: ParticipantSource;
119
+ onSelectParticipant: (participant: Participant) => void;
120
+ onClose: () => void;
121
+ existingParticipantIds?: Set<string>;
122
+ participantLabel?: string;
123
+ searchPlaceholder?: string;
124
+ className?: string;
125
+ }
126
+ /**
127
+ * MessagingProvider component props
128
+ */
129
+ export interface MessagingProviderProps {
130
+ children: React.ReactNode;
131
+ user: MessagingUser | null;
132
+ serviceConfig: Omit<StreamChatServiceConfig, 'apiKey'>;
133
+ apiKey: string;
134
+ capabilities?: MessagingCapabilities;
135
+ customization?: MessagingCustomization;
136
+ debug?: boolean;
137
+ }
138
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,33 +1,19 @@
1
- import SelectPill from '@linktr.ee/component-library/InputSelectPill'
2
- import SelectPillGroup from '@linktr.ee/component-library/InputSelectPillGroup'
3
- import { NotePencilIcon } from '@phosphor-icons/react'
4
1
  import classNames from 'classnames'
5
- import React, { useState } from 'react'
6
- import {
7
- ChannelList as StreamChannelList,
8
- useChatContext,
9
- } from 'stream-chat-react'
2
+ import React from 'react'
3
+ import { ChannelList as StreamChannelList } from 'stream-chat-react'
10
4
 
11
5
  import { useMessagingContext } from '../../providers/MessagingProvider'
12
6
  import type { ChannelListProps } from '../../types'
13
- import { IconButton } from '../IconButton'
14
7
 
15
8
  import CustomChannelPreview from './CustomChannelPreview'
16
9
 
17
- enum ChannelFilter {
18
- All,
19
- Unread,
20
- }
21
-
22
10
  /**
23
11
  * Channel list component with customizable header and actions
24
12
  */
25
13
  export const ChannelList: React.FC<ChannelListProps> = ({
26
14
  onChannelSelect,
27
15
  selectedChannel,
28
- showStartConversation = false,
29
- onStartConversation,
30
- participantLabel = 'participants',
16
+ filters,
31
17
  className,
32
18
  }) => {
33
19
  // Track renders
@@ -41,55 +27,10 @@ export const ChannelList: React.FC<ChannelListProps> = ({
41
27
  console.log('📺 [ChannelList] 🔄 RENDER START', {
42
28
  renderCount: renderCountRef.current,
43
29
  selectedChannelId: selectedChannel?.id,
44
- showStartConversation,
45
- participantLabel,
30
+ filters,
46
31
  })
47
32
  }
48
33
 
49
- const { client } = useChatContext()
50
-
51
- if (debug) {
52
- console.log('📺 [ChannelList] 📡 CHAT CONTEXT', {
53
- renderCount: renderCountRef.current,
54
- hasClient: !!client,
55
- clientUserId: client?.userID,
56
- clientConnected: client?.wsConnection?.isHealthy,
57
- })
58
- }
59
-
60
- const [staticFilters, setStaticFilters] = useState<{
61
- type: string
62
- last_message_at: { $exists: boolean }
63
- has_unread: boolean | undefined
64
- }>({
65
- type: 'messaging',
66
- last_message_at: { $exists: true },
67
- has_unread: undefined,
68
- })
69
-
70
- // Filter for messaging channels
71
- const filters = React.useMemo(() => {
72
- const userId = client.userID
73
-
74
- const newFilters = {
75
- ...staticFilters,
76
- ...(userId && {
77
- members: { $in: [userId] },
78
- hidden: false,
79
- }),
80
- }
81
-
82
- if (debug) {
83
- console.log('📺 [ChannelList] 🔍 FILTERS MEMOIZED', {
84
- renderCount: renderCountRef.current,
85
- userId,
86
- filters: newFilters,
87
- })
88
- }
89
-
90
- return newFilters
91
- }, [client.userID, debug, staticFilters])
92
-
93
34
  return (
94
35
  <div
95
36
  className={classNames(
@@ -97,49 +38,6 @@ export const ChannelList: React.FC<ChannelListProps> = ({
97
38
  className
98
39
  )}
99
40
  >
100
- {/* Header */}
101
- <div className="px-4 py-4 border-b border-sand bg-chalk">
102
- <div className="flex items-center justify-between gap-3 min-h-10 min-w-0">
103
- <div>
104
- <h2 className="text-lg font-semibold text-charcoal">
105
- Conversations
106
- </h2>
107
- <SelectPillGroup>
108
- <SelectPill
109
- checked={!filters.has_unread}
110
- name="All"
111
- onChange={() =>
112
- setStaticFilters((state) => ({
113
- ...state,
114
- has_unread: undefined,
115
- }))
116
- }
117
- value={ChannelFilter.All}
118
- />
119
- <SelectPill
120
- checked={filters.has_unread}
121
- name="Unread"
122
- onChange={() =>
123
- setStaticFilters((state) => ({ ...state, has_unread: true }))
124
- }
125
- value={ChannelFilter.Unread}
126
- />
127
- </SelectPillGroup>
128
- </div>
129
- <div className="flex items-center gap-2">
130
- {showStartConversation && onStartConversation && (
131
- <IconButton
132
- label="Start a new conversation"
133
- onClick={onStartConversation}
134
- className="inline-flex size-10 items-center justify-center"
135
- >
136
- <NotePencilIcon className="h-5 w-5" />
137
- </IconButton>
138
- )}
139
- </div>
140
- </div>
141
- </div>
142
-
143
41
  {/* Channel List */}
144
42
  <div className="flex-1 overflow-hidden min-w-0">
145
43
  {(() => {
@@ -147,13 +45,12 @@ export const ChannelList: React.FC<ChannelListProps> = ({
147
45
  console.log('📺 [ChannelList] 🎬 RENDERING STREAM CHANNEL LIST', {
148
46
  renderCount: renderCountRef.current,
149
47
  filters,
150
- hasClient: !!client,
151
- clientUserId: client?.userID,
152
48
  })
153
49
  }
154
50
 
155
51
  return (
156
52
  <StreamChannelList
53
+ key={JSON.stringify(filters)}
157
54
  filters={filters}
158
55
  sort={{ last_message_at: -1 }}
159
56
  options={{ limit: 30 }}
@@ -1,6 +1,5 @@
1
1
  import classNames from 'classnames'
2
2
  import React from 'react'
3
-
4
3
  export interface FaqListItemProps {
5
4
  question: string
6
5
  onClick: () => void
@@ -25,6 +25,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
25
25
  initialParticipantData,
26
26
  CustomChannelEmptyState,
27
27
  showChannelList = true,
28
+ filters,
28
29
  }) => {
29
30
  const {
30
31
  service,
@@ -56,6 +57,28 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
56
57
  participantLabel = 'participants',
57
58
  } = capabilities
58
59
 
60
+ // Create default filters and merge with provided filters
61
+ const channelFilters = React.useMemo(() => {
62
+ const userId = client?.userID
63
+
64
+ // Base filters that should always be present
65
+ const baseFilters = {
66
+ type: 'messaging',
67
+ last_message_at: { $exists: true },
68
+ ...(userId && {
69
+ members: { $in: [userId] },
70
+ hidden: false,
71
+ }),
72
+ }
73
+
74
+ // Merge provided filters with base filters
75
+ // Provided filters can override base filters if needed
76
+ return {
77
+ ...baseFilters,
78
+ ...filters,
79
+ }
80
+ }, [filters, client?.userID])
81
+
59
82
  // Track if we've already synced channels to prevent repeated API calls
60
83
  const syncedRef = useRef<string | null>(null)
61
84
 
@@ -405,11 +428,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
405
428
  <ChannelList
406
429
  onChannelSelect={handleChannelSelect}
407
430
  selectedChannel={selectedChannel || undefined}
408
- showStartConversation={
409
- showStartConversation && Boolean(participantSource)
410
- }
411
- onStartConversation={handleStartConversation}
412
- participantLabel={participantLabel}
431
+ filters={channelFilters}
413
432
  />
414
433
  </div>
415
434
 
package/src/types.ts CHANGED
@@ -2,7 +2,7 @@ import type {
2
2
  MessagingUser,
3
3
  StreamChatServiceConfig,
4
4
  } from '@linktr.ee/messaging-core'
5
- import type { Channel } from 'stream-chat'
5
+ import type { Channel, ChannelFilters } from 'stream-chat'
6
6
 
7
7
  /**
8
8
  * Generic participant interface for different host environments
@@ -49,7 +49,6 @@ export interface MessagingCapabilities {
49
49
  export interface MessagingCustomization {
50
50
  theme?: 'light' | 'dark' | 'auto'
51
51
  accentColor?: string
52
- showParticipantStatus?: boolean
53
52
  }
54
53
 
55
54
  /**
@@ -94,6 +93,11 @@ export interface MessagingShellProps {
94
93
  * to show only the channel view without the list.
95
94
  */
96
95
  showChannelList?: boolean
96
+
97
+ /**
98
+ * Filters for channel list. Passed through to StreamChat ChannelList.
99
+ */
100
+ filters?: ChannelFilters
97
101
  }
98
102
 
99
103
  /**
@@ -106,6 +110,7 @@ export interface ChannelListProps {
106
110
  onStartConversation?: () => void
107
111
  participantLabel?: string
108
112
  className?: string
113
+ filters: ChannelFilters
109
114
  }
110
115
 
111
116
  /**