@linktr.ee/messaging-react 1.0.1 → 1.1.0-ks-migrate-styles-1760927135

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 (41) hide show
  1. package/dist/assets/index.css +1 -0
  2. package/dist/index.d.ts +2 -1
  3. package/dist/index.js +846 -1080
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -5
  6. package/src/components/ActionButton/ActionButton.stories.tsx +2 -1
  7. package/src/components/ActionButton/ActionButton.test.tsx +2 -0
  8. package/src/components/Avatar/Avatar.stories.tsx +2 -1
  9. package/src/components/Avatar/avatarColors.ts +21 -22
  10. package/src/components/Avatar/index.tsx +2 -1
  11. package/src/components/ChannelList/ChannelList.stories.tsx +4 -2
  12. package/src/components/ChannelList/CustomChannelPreview.stories.tsx +31 -27
  13. package/src/components/ChannelList/CustomChannelPreview.tsx +29 -28
  14. package/src/components/ChannelList/index.tsx +43 -35
  15. package/src/components/ChannelView.tsx +150 -127
  16. package/src/components/CloseButton/index.tsx +4 -5
  17. package/src/components/IconButton/IconButton.stories.tsx +3 -3
  18. package/src/components/Loading/Loading.stories.tsx +2 -1
  19. package/src/components/Loading/index.tsx +7 -9
  20. package/src/components/MessagingShell/EmptyState.stories.tsx +2 -1
  21. package/src/components/MessagingShell/EmptyState.tsx +23 -20
  22. package/src/components/MessagingShell/ErrorState.stories.tsx +2 -1
  23. package/src/components/MessagingShell/LoadingState.stories.tsx +2 -1
  24. package/src/components/MessagingShell/LoadingState.tsx +3 -5
  25. package/src/components/MessagingShell/index.tsx +159 -135
  26. package/src/components/ParticipantPicker/ParticipantItem.stories.tsx +4 -2
  27. package/src/components/ParticipantPicker/ParticipantItem.tsx +25 -21
  28. package/src/components/ParticipantPicker/ParticipantPicker.stories.tsx +4 -2
  29. package/src/components/ParticipantPicker/ParticipantPicker.tsx +104 -76
  30. package/src/components/ParticipantPicker/index.tsx +93 -72
  31. package/src/components/SearchInput/SearchInput.stories.tsx +2 -1
  32. package/src/components/SearchInput/SearchInput.test.tsx +4 -2
  33. package/src/components/SearchInput/index.tsx +14 -15
  34. package/src/hooks/useParticipants.ts +1 -0
  35. package/src/index.ts +3 -0
  36. package/src/providers/MessagingProvider.tsx +213 -135
  37. package/src/stories/mocks.tsx +18 -19
  38. package/src/styles.css +75 -0
  39. package/src/test/setup.ts +11 -12
  40. package/src/test/utils.tsx +6 -7
  41. package/src/types.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.0.1",
3
+ "version": "1.1.0-ks-migrate-styles-1760927135",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,7 +10,8 @@
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js"
13
- }
13
+ },
14
+ "./styles.css": "./dist/assets/index.css"
14
15
  },
15
16
  "license": "UNLICENSED",
16
17
  "files": [
@@ -33,7 +34,7 @@
33
34
  },
34
35
  "dependencies": {
35
36
  "@linktr.ee/component-library": "*",
36
- "@linktr.ee/messaging-core": "*",
37
+ "@linktr.ee/messaging-core": "^1.0.1",
37
38
  "@phosphor-icons/react": "^2.1.9",
38
39
  "stream-chat-react": "^13.9.0"
39
40
  },
@@ -61,7 +62,7 @@
61
62
  "react-dom": "^18.3.1",
62
63
  "storybook": "^8.5.0",
63
64
  "stream-chat": "^9.22.1",
64
- "tailwindcss": "3.2.7",
65
+ "tailwindcss": "^3.4.17",
65
66
  "tailwindcss-animate": "^1.0.7",
66
67
  "typescript": "5.9.2",
67
68
  "vite": "^6.0.7",
@@ -75,4 +76,4 @@
75
76
  "stream-chat": "^9.22.1",
76
77
  "stream-chat-react": "^13.9.0"
77
78
  }
78
- }
79
+ }
@@ -1,7 +1,8 @@
1
1
  import type { Meta, StoryFn } from '@storybook/react'
2
- import ActionButton from '.'
3
2
  import React from 'react'
4
3
 
4
+ import ActionButton from '.'
5
+
5
6
 
6
7
  type ComponentProps = React.ComponentProps<typeof ActionButton>
7
8
 
@@ -1,5 +1,7 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
+
2
3
  import { renderWithProviders, screen, userEvent } from '../../test/utils';
4
+
3
5
  import ActionButton from '.';
4
6
 
5
7
  describe('ActionButton', () => {
@@ -1,7 +1,8 @@
1
1
  import type { Meta, StoryFn } from '@storybook/react'
2
- import { Avatar } from './index'
3
2
  import React from 'react'
4
3
 
4
+ import { Avatar } from './index'
5
+
5
6
  type ComponentProps = React.ComponentProps<typeof Avatar>
6
7
 
7
8
  const meta: Meta<ComponentProps> = {
@@ -3,34 +3,33 @@
3
3
  * Uses the ID to deterministically select from design system colors
4
4
  */
5
5
  export function getAvatarColors(id: string): {
6
- bgColor: string;
7
- textColor: string;
6
+ bgColor: string
7
+ textColor: string
8
8
  } {
9
9
  // Map of color combinations from Linktree design system
10
10
  // Selected for good contrast at 20% opacity
11
11
  const colorPairs = [
12
- { bgColor: "bg-primary bg-opacity-20", textColor: "text-primary" }, // #8129D9 - purple
13
- { bgColor: "bg-forest bg-opacity-20", textColor: "text-forest" }, // #254f1a - dark green
14
- { bgColor: "bg-iris bg-opacity-20", textColor: "text-iris" }, // #061492 - dark blue
15
- { bgColor: "bg-shade bg-opacity-20", textColor: "text-shade" }, // #1e2330 - dark blue-gray
16
- { bgColor: "bg-dahlia bg-opacity-20", textColor: "text-dahlia" }, // #502274 - dark purple
17
- { bgColor: "bg-orchid bg-opacity-20", textColor: "text-orchid" }, // #d717e7 - magenta
18
- { bgColor: "bg-currant bg-opacity-20", textColor: "text-currant" }, // #780016 - dark red
19
- { bgColor: "bg-apple bg-opacity-20", textColor: "text-apple" }, // #c41500 - red
20
- { bgColor: "bg-rose bg-opacity-20", textColor: "text-rose" }, // #fc3e4b - pink
21
- { bgColor: "bg-root bg-opacity-20", textColor: "text-root" }, // #4c2e05 - brown
22
- { bgColor: "bg-poppy bg-opacity-20", textColor: "text-poppy" }, // #ff6c02 - orange
23
- { bgColor: "bg-moss bg-opacity-20", textColor: "text-moss" }, // #70764d - olive green
24
- ];
12
+ { bgColor: 'bg-primary/20', textColor: 'text-primary' }, // #8129D9 - purple
13
+ { bgColor: 'bg-forest/20', textColor: 'text-forest' }, // #254f1a - dark green
14
+ { bgColor: 'bg-iris/20', textColor: 'text-iris' }, // #061492 - dark blue
15
+ { bgColor: 'bg-shade/20', textColor: 'text-shade' }, // #1e2330 - dark blue-gray
16
+ { bgColor: 'bg-dahlia/20', textColor: 'text-dahlia' }, // #502274 - dark purple
17
+ { bgColor: 'bg-orchid/20', textColor: 'text-orchid' }, // #d717e7 - magenta
18
+ { bgColor: 'bg-currant/20', textColor: 'text-currant' }, // #780016 - dark red
19
+ { bgColor: 'bg-apple/20', textColor: 'text-apple' }, // #c41500 - red
20
+ { bgColor: 'bg-rose/20', textColor: 'text-rose' }, // #fc3e4b - pink
21
+ { bgColor: 'bg-root/20', textColor: 'text-root' }, // #4c2e05 - brown
22
+ { bgColor: 'bg-poppy/20', textColor: 'text-poppy' }, // #ff6c02 - orange
23
+ { bgColor: 'bg-moss/20', textColor: 'text-moss' }, // #70764d - olive green
24
+ ]
25
25
 
26
26
  // Simple hash function to get consistent index
27
- let hash = 0;
27
+ let hash = 0
28
28
  for (let i = 0; i < id.length; i++) {
29
- hash = ((hash << 5) - hash) + id.charCodeAt(i);
30
- hash = hash & hash; // Convert to 32bit integer
29
+ hash = (hash << 5) - hash + id.charCodeAt(i)
30
+ hash = hash & hash // Convert to 32bit integer
31
31
  }
32
-
33
- const index = Math.abs(hash) % colorPairs.length;
34
- return colorPairs[index];
35
- }
36
32
 
33
+ const index = Math.abs(hash) % colorPairs.length
34
+ return colorPairs[index]
35
+ }
@@ -1,5 +1,6 @@
1
- import React from 'react';
2
1
  import classNames from 'classnames';
2
+ import React from 'react';
3
+
3
4
  import { getAvatarColors } from './avatarColors';
4
5
 
5
6
  export interface AvatarProps {
@@ -1,8 +1,10 @@
1
1
  import type { Meta, StoryFn } from '@storybook/react'
2
- import { ChannelList } from '.'
2
+ import React from 'react'
3
+
3
4
  import { MockChatProvider } from '../../stories/mocks'
4
5
 
5
- import React from 'react'
6
+ import { ChannelList } from '.'
7
+
6
8
 
7
9
  type ComponentProps = React.ComponentProps<typeof ChannelList>
8
10
 
@@ -1,6 +1,8 @@
1
1
  import type { Meta, StoryFn } from '@storybook/react'
2
- import CustomChannelPreview from './CustomChannelPreview'
3
2
  import React from 'react'
3
+ import { Channel, LocalMessage, StreamChat } from 'stream-chat'
4
+
5
+ import CustomChannelPreview from './CustomChannelPreview'
4
6
 
5
7
  type ComponentProps = React.ComponentProps<typeof CustomChannelPreview>
6
8
 
@@ -8,13 +10,9 @@ const meta: Meta<ComponentProps> = {
8
10
  title: 'ChannelList/CustomChannelPreview',
9
11
  component: CustomChannelPreview,
10
12
  parameters: {
11
- layout: 'centered'
13
+ layout: 'centered',
12
14
  },
13
- decorators: [
14
- (Story) => (
15
- <Story />
16
- )
17
- ]
15
+ decorators: [(Story) => <Story />],
18
16
  }
19
17
  export default meta
20
18
 
@@ -34,7 +32,7 @@ const createMockChannel = (options: {
34
32
  lastMessageText?: string
35
33
  lastMessageTime?: Date
36
34
  unreadCount?: number
37
- }): any => {
35
+ }): Channel => {
38
36
  const {
39
37
  id,
40
38
  participantName,
@@ -50,7 +48,7 @@ const createMockChannel = (options: {
50
48
  cid: `messaging:${id}`,
51
49
  _client: {
52
50
  userID: mockUser.id,
53
- },
51
+ } as unknown as StreamChat,
54
52
  state: {
55
53
  members: {
56
54
  [mockUser.id]: {
@@ -66,20 +64,22 @@ const createMockChannel = (options: {
66
64
  user_id: participantId,
67
65
  },
68
66
  },
69
- messages: lastMessageText ? [
70
- {
71
- id: `msg-${id}-1`,
72
- text: lastMessageText,
73
- created_at: lastMessageTime.toISOString(),
74
- user: {
75
- id: participantId,
76
- name: participantName,
77
- },
78
- },
79
- ] : [],
67
+ messages: lastMessageText
68
+ ? ([
69
+ {
70
+ id: `msg-${id}-1`,
71
+ text: lastMessageText,
72
+ created_at: lastMessageTime.toISOString(),
73
+ user: {
74
+ id: participantId,
75
+ name: participantName,
76
+ },
77
+ },
78
+ ] as unknown as LocalMessage[])
79
+ : ([] as LocalMessage[]),
80
80
  unreadCount,
81
81
  },
82
- }
82
+ } as unknown as Channel
83
83
  }
84
84
 
85
85
  const Template: StoryFn<ComponentProps> = (args) => {
@@ -181,7 +181,8 @@ LongMessage.args = {
181
181
  participantName: 'Grace Lee',
182
182
  participantId: 'participant-7',
183
183
  participantImage: 'https://i.pravatar.cc/150?img=7',
184
- lastMessageText: 'This is a very long message that should be truncated because it contains way too much text to display in the preview. We want to make sure the component handles this gracefully.',
184
+ lastMessageText:
185
+ 'This is a very long message that should be truncated because it contains way too much text to display in the preview. We want to make sure the component handles this gracefully.',
185
186
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 2), // 2 hours ago
186
187
  }),
187
188
  onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
@@ -219,7 +220,9 @@ SelectedWithUnread.args = {
219
220
  }
220
221
 
221
222
  export const MultipleChannels: StoryFn = () => {
222
- const [selectedChannelId, setSelectedChannelId] = React.useState<string | null>('channel-2')
223
+ const [selectedChannelId, _setSelectedChannelId] = React.useState<
224
+ string | null
225
+ >('channel-2')
223
226
 
224
227
  const channels = [
225
228
  createMockChannel({
@@ -257,11 +260,12 @@ export const MultipleChannels: StoryFn = () => {
257
260
  }),
258
261
  ]
259
262
 
260
- const selectedChannel = channels.find(c => c.id === selectedChannelId) || null
263
+ const selectedChannel =
264
+ channels.find((c) => c.id === selectedChannelId) || null
261
265
 
262
266
  return (
263
267
  <div className="w-[360px] bg-chalk border border-sand rounded-lg overflow-hidden">
264
- {channels.map(channel => (
268
+ {channels.map((channel) => (
265
269
  <CustomChannelPreview
266
270
  key={channel.id}
267
271
  channel={channel}
@@ -295,9 +299,9 @@ WithVeryLongUrl.args = {
295
299
  participantName: 'Julia Martinez',
296
300
  participantId: 'participant-long-url',
297
301
  participantImage: 'https://i.pravatar.cc/150?img=11',
298
- lastMessageText: 'https://example.com/very/long/path/with/many/segments/and/query/parameters?param1=value1&param2=value2&param3=value3&param4=value4&param5=very-long-value-that-makes-the-url-extremely-long',
302
+ lastMessageText:
303
+ 'https://example.com/very/long/path/with/many/segments/and/query/parameters?param1=value1&param2=value2&param3=value3&param4=value4&param5=very-long-value-that-makes-the-url-extremely-long',
299
304
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 20), // 20 minutes ago
300
305
  }),
301
306
  onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
302
307
  }
303
-
@@ -1,48 +1,49 @@
1
- import React from 'react';
2
- import { ChannelPreviewUIComponentProps } from 'stream-chat-react';
3
- import { Channel } from 'stream-chat';
4
- import classNames from 'classnames';
5
- import { Avatar } from '../Avatar';
1
+ import classNames from 'classnames'
2
+ import React from 'react'
3
+ import { Channel } from 'stream-chat'
4
+ import { ChannelPreviewUIComponentProps } from 'stream-chat-react'
5
+
6
+ import { Avatar } from '../Avatar'
6
7
 
7
8
  /**
8
9
  * Custom channel preview that handles selection
9
10
  */
10
11
  const CustomChannelPreview: React.FC<
11
12
  ChannelPreviewUIComponentProps & {
12
- selectedChannel?: Channel;
13
- onChannelSelect: (channel: Channel) => void;
14
- debug?: boolean;
13
+ selectedChannel?: Channel | null
14
+ onChannelSelect: (channel: Channel) => void
15
+ debug?: boolean
15
16
  }
16
- > = ({ channel, selectedChannel, onChannelSelect, debug = false, ...props }) => {
17
- const isSelected = selectedChannel?.id === channel?.id;
17
+ > = ({ channel, selectedChannel, onChannelSelect, debug = false }) => {
18
+ const isSelected = selectedChannel?.id === channel?.id
18
19
 
19
20
  const handleClick = () => {
20
21
  if (channel) {
21
- onChannelSelect(channel);
22
+ onChannelSelect(channel)
22
23
  }
23
- };
24
+ }
24
25
 
25
26
  // Get participant info
26
- const members = Object.values(channel?.state?.members || {});
27
- const participant = members.find(member =>
28
- member.user?.id && member.user.id !== channel?._client?.userID
29
- );
30
- const participantName = participant?.user?.name || 'Conversation';
31
- const participantImage = participant?.user?.image;
32
- const participantInitial = participantName.charAt(0).toUpperCase();
27
+ const members = Object.values(channel?.state?.members || {})
28
+ const participant = members.find(
29
+ (member) => member.user?.id && member.user.id !== channel?._client?.userID
30
+ )
31
+ const participantName = participant?.user?.name || 'Conversation'
32
+ const participantImage = participant?.user?.image
33
33
 
34
34
  // Get last message and format timestamp
35
- const lastMessage = channel?.state?.messages?.[channel.state.messages.length - 1];
36
- const lastMessageText = lastMessage?.text || 'No messages yet';
35
+ const lastMessage =
36
+ channel?.state?.messages?.[channel.state.messages.length - 1]
37
+ const lastMessageText = lastMessage?.text || 'No messages yet'
37
38
  const lastMessageTime = lastMessage?.created_at
38
39
  ? new Date(lastMessage.created_at).toLocaleTimeString([], {
39
40
  hour: '2-digit',
40
41
  minute: '2-digit',
41
42
  })
42
- : '';
43
+ : ''
43
44
 
44
45
  // Get unread count from channel state
45
- const unread = channel?.state?.unreadCount || 0;
46
+ const unread = channel?.state?.unreadCount || 0
46
47
 
47
48
  if (debug) {
48
49
  console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {
@@ -51,7 +52,7 @@ const CustomChannelPreview: React.FC<
51
52
  participantName,
52
53
  unread,
53
54
  hasTimestamp: !!lastMessageTime,
54
- });
55
+ })
55
56
  }
56
57
 
57
58
  return (
@@ -61,7 +62,7 @@ const CustomChannelPreview: React.FC<
61
62
  className={classNames(
62
63
  'w-full px-4 py-3 transition-colors border-b border-sand text-left max-w-full overflow-hidden focus-ring',
63
64
  {
64
- 'bg-primary-alt bg-opacity-10 border-l-4 border-l-primary': isSelected,
65
+ 'bg-primary-alt/10 border-l-4 border-l-primary': isSelected,
65
66
  'hover:bg-sand': !isSelected,
66
67
  }
67
68
  )}
@@ -108,7 +109,7 @@ const CustomChannelPreview: React.FC<
108
109
  </div>
109
110
  </div>
110
111
  </button>
111
- );
112
- };
112
+ )
113
+ }
113
114
 
114
- export default CustomChannelPreview;
115
+ export default CustomChannelPreview
@@ -1,13 +1,16 @@
1
- import React from 'react';
2
- import { NotePencilIcon } from "@phosphor-icons/react/dist/csr/NotePencil";
1
+ import { NotePencilIcon } from '@phosphor-icons/react'
2
+ import classNames from 'classnames'
3
+ import React from 'react'
4
+ import {
5
+ ChannelList as StreamChannelList,
6
+ useChatContext,
7
+ } from 'stream-chat-react'
3
8
 
4
- import classNames from 'classnames';
5
- import { ChannelList as StreamChannelList, useChatContext } from 'stream-chat-react';
6
- import type { ChannelListProps } from '../../types';
7
- import { IconButton } from '../IconButton';
8
- import { useMessagingContext } from '../../providers/MessagingProvider';
9
- import CustomChannelPreview from './CustomChannelPreview';
9
+ import { useMessagingContext } from '../../providers/MessagingProvider'
10
+ import type { ChannelListProps } from '../../types'
11
+ import { IconButton } from '../IconButton'
10
12
 
13
+ import CustomChannelPreview from './CustomChannelPreview'
11
14
 
12
15
  /**
13
16
  * Channel list component with customizable header and actions
@@ -21,52 +24,57 @@ export const ChannelList: React.FC<ChannelListProps> = ({
21
24
  className,
22
25
  }) => {
23
26
  // Track renders
24
- const renderCountRef = React.useRef(0);
25
- renderCountRef.current++;
27
+ const renderCountRef = React.useRef(0)
28
+ renderCountRef.current++
26
29
 
27
30
  // Get debug flag from context
28
- const { debug = false } = useMessagingContext();
31
+ const { debug = false } = useMessagingContext()
29
32
 
30
33
  if (debug) {
31
34
  console.log('📺 [ChannelList] 🔄 RENDER START', {
32
35
  renderCount: renderCountRef.current,
33
36
  selectedChannelId: selectedChannel?.id,
34
37
  showStartConversation,
35
- participantLabel
36
- });
38
+ participantLabel,
39
+ })
37
40
  }
38
41
 
39
- const { client } = useChatContext();
42
+ const { client } = useChatContext()
40
43
 
41
44
  if (debug) {
42
45
  console.log('📺 [ChannelList] 📡 CHAT CONTEXT', {
43
46
  renderCount: renderCountRef.current,
44
47
  hasClient: !!client,
45
48
  clientUserId: client?.userID,
46
- clientConnected: client?.wsConnection?.isHealthy
47
- });
49
+ clientConnected: client?.wsConnection?.isHealthy,
50
+ })
48
51
  }
49
52
 
50
53
  // Filter for messaging channels
51
54
  const filters = React.useMemo(() => {
52
- const userId = client.userID;
55
+ const userId = client.userID
53
56
  const newFilters = userId
54
57
  ? { type: 'messaging', members: { $in: [userId] }, hidden: false }
55
- : { type: 'messaging' };
56
-
58
+ : { type: 'messaging' }
59
+
57
60
  if (debug) {
58
61
  console.log('📺 [ChannelList] 🔍 FILTERS MEMOIZED', {
59
62
  renderCount: renderCountRef.current,
60
63
  userId,
61
- filters: newFilters
62
- });
64
+ filters: newFilters,
65
+ })
63
66
  }
64
-
65
- return newFilters;
66
- }, [client.userID, debug]);
67
+
68
+ return newFilters
69
+ }, [client.userID, debug])
67
70
 
68
71
  return (
69
- <div className={classNames('h-full flex flex-col min-w-0 overflow-hidden', className)}>
72
+ <div
73
+ className={classNames(
74
+ 'h-full flex flex-col min-w-0 overflow-hidden',
75
+ className
76
+ )}
77
+ >
70
78
  {/* Header */}
71
79
  <div className="px-4 py-4 border-b border-sand bg-chalk">
72
80
  <div className="flex items-center justify-between gap-3 min-h-10 min-w-0">
@@ -93,10 +101,10 @@ export const ChannelList: React.FC<ChannelListProps> = ({
93
101
  renderCount: renderCountRef.current,
94
102
  filters,
95
103
  hasClient: !!client,
96
- clientUserId: client?.userID
97
- });
104
+ clientUserId: client?.userID,
105
+ })
98
106
  }
99
-
107
+
100
108
  return (
101
109
  <StreamChannelList
102
110
  filters={filters}
@@ -107,10 +115,10 @@ export const ChannelList: React.FC<ChannelListProps> = ({
107
115
  console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {
108
116
  channelId: props.channel?.id,
109
117
  selectedChannelId: selectedChannel?.id,
110
- isSelected: selectedChannel?.id === props.channel?.id
111
- });
118
+ isSelected: selectedChannel?.id === props.channel?.id,
119
+ })
112
120
  }
113
-
121
+
114
122
  return (
115
123
  <CustomChannelPreview
116
124
  {...props}
@@ -118,12 +126,12 @@ export const ChannelList: React.FC<ChannelListProps> = ({
118
126
  onChannelSelect={onChannelSelect}
119
127
  debug={debug}
120
128
  />
121
- );
129
+ )
122
130
  }}
123
131
  />
124
- );
132
+ )
125
133
  })()}
126
134
  </div>
127
135
  </div>
128
- );
129
- };
136
+ )
137
+ }