@rpg-engine/long-bow 0.5.45 → 0.5.46

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.
@@ -3,4 +3,5 @@ import { IChatRevampProps } from '../components/ChatRevamp/ChatRevamp';
3
3
  declare const meta: Meta;
4
4
  export default meta;
5
5
  export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IChatRevampProps>;
6
- export declare const PrivateCharacters: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IChatRevampProps>;
6
+ export declare const Private: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IChatRevampProps>;
7
+ export declare const Trade: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IChatRevampProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.5.45",
3
+ "version": "0.5.46",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -83,7 +83,7 @@
83
83
  },
84
84
  "dependencies": {
85
85
  "@rollup/plugin-image": "^2.1.1",
86
- "@rpg-engine/shared": "^0.8.92",
86
+ "@rpg-engine/shared": "^0.9.11",
87
87
  "dayjs": "^1.11.2",
88
88
  "font-awesome": "^4.7.0",
89
89
  "fs-extra": "^10.1.0",
@@ -1,16 +1,11 @@
1
- import { IChatMessage, IPrivateChatMessage } from '@rpg-engine/shared';
2
1
  import dayjs from 'dayjs';
3
2
  import React, { useEffect, useState } from 'react';
4
3
  import { ErrorBoundary } from 'react-error-boundary';
5
4
  import { RxPaperPlane } from 'react-icons/rx';
6
5
  import styled from 'styled-components';
6
+ import { ChatMessage } from '../ChatRevamp/ChatRevamp';
7
7
  import { Column } from '../shared/Column';
8
8
 
9
- interface IEmitter {
10
- _id: string;
11
- name: string;
12
- }
13
-
14
9
  export interface IStyles {
15
10
  textColor?: string;
16
11
  buttonColor?: string;
@@ -19,8 +14,13 @@ export interface IStyles {
19
14
  height?: string;
20
15
  }
21
16
 
17
+ export interface IEmitter {
18
+ _id: string;
19
+ name: string;
20
+ }
21
+
22
22
  export interface IChatProps {
23
- chatMessages: IChatMessage[] | IPrivateChatMessage[];
23
+ chatMessages: ChatMessage[];
24
24
  onSendChatMessage: (message: string) => void;
25
25
  onCloseButton: () => void;
26
26
  onFocus?: () => void;
@@ -80,9 +80,7 @@ export const Chat: React.FC<IChatProps> = ({
80
80
  } ${message}`;
81
81
  };
82
82
 
83
- const onRenderChatMessages = (
84
- chatMessages: (IChatMessage | IPrivateChatMessage)[]
85
- ) => {
83
+ const onRenderChatMessages = (chatMessages: ChatMessage[]) => {
86
84
  return chatMessages?.length ? (
87
85
  chatMessages?.map((chatMessage, index) => (
88
86
  <Message
@@ -161,8 +159,8 @@ interface IButtonProps {
161
159
  }
162
160
 
163
161
  const ChatContainer = styled.div<IContainerProps>`
164
- height: ${props => props.height};
165
- width: ${({ width }) => width};
162
+ height: ${props => props.height} !important;
163
+ width: 100%;
166
164
  padding: 10px;
167
165
  background-color: rgba(0, 0, 0, 0.2);
168
166
  height: auto;
@@ -178,10 +176,7 @@ const TextField = styled.input`
178
176
  const MessagesContainer = styled.div`
179
177
  height: 70%;
180
178
  margin-bottom: 10px;
181
- .chat-body {
182
- max-height: auto;
183
- overflow-y: auto;
184
- }
179
+ overflow-y: auto;
185
180
  `;
186
181
 
187
182
  const Message = styled.div<IMessageProps>`
@@ -2,27 +2,28 @@ import {
2
2
  ICharacter,
3
3
  IChatMessage,
4
4
  IPrivateChatMessage,
5
+ ITradeChatMessage,
5
6
  } from '@rpg-engine/shared';
6
7
  import React, { useEffect, useState } from 'react';
8
+ import { RxCross2, RxMagnifyingGlass } from 'react-icons/rx';
7
9
  import styled from 'styled-components';
8
10
  import { uiColors } from '../../constants/uiColors';
11
+ import { uiFonts } from '../../constants/uiFonts';
9
12
  import { Chat, IStyles } from '../Chat/Chat';
10
13
  import { SearchCharacter } from './SearchCharacter';
11
14
 
12
- export interface ITabStyles {
13
- width?: string;
14
- height?: string;
15
- }
16
-
17
15
  export type PrivateChatCharacter = Pick<ICharacter, '_id' | 'name'>;
18
16
 
17
+ export type ChatMessage =
18
+ | IChatMessage
19
+ | IPrivateChatMessage
20
+ | ITradeChatMessage;
19
21
  export interface IChatRevampProps {
20
- chatMessages: IChatMessage[] | IPrivateChatMessage[];
22
+ chatMessages: ChatMessage[];
21
23
  onSendGlobalChatMessage: (message: string) => void;
22
24
  onCloseButton: () => void;
23
25
  onFocus?: () => void;
24
26
  onBlur?: () => void;
25
- opacity?: number;
26
27
  styles?: IStyles;
27
28
  tabs: { label: string; id: string }[];
28
29
  activeTab: string;
@@ -31,6 +32,12 @@ export interface IChatRevampProps {
31
32
  onChangeCharacterName: (characterName: string) => void;
32
33
  onCharacterClick?: (character: PrivateChatCharacter) => void;
33
34
  onSendPrivateChatMessage: (message: string) => void;
35
+ recentChatCharacters?: PrivateChatCharacter[];
36
+ recentSelectedChatCharacterId?: string;
37
+ onPreviousChatCharacterClick?: (character: PrivateChatCharacter) => void;
38
+ onRemoveRecentChatCharacter?: (character: PrivateChatCharacter) => void;
39
+ unseenMessageCharacterIds?: string[];
40
+ onSendTradeMessage: (message: string) => void;
34
41
  }
35
42
 
36
43
  export const ChatRevamp = ({
@@ -47,14 +54,30 @@ export const ChatRevamp = ({
47
54
  privateChatCharacters,
48
55
  onCharacterClick,
49
56
  onSendPrivateChatMessage,
57
+ recentChatCharacters,
58
+ recentSelectedChatCharacterId = '',
59
+ onPreviousChatCharacterClick,
60
+ onRemoveRecentChatCharacter,
61
+ unseenMessageCharacterIds = [],
62
+ onSendTradeMessage,
50
63
  }: IChatRevampProps) => {
51
- const [showSearchCharacter, setShowSearchCharacter] = useState(true);
64
+ const [showSearchCharacterUI, setShowSearchCharacterUI] = useState(true);
65
+ const [showRecentChats, setShowRecentChats] = useState(false);
52
66
 
53
67
  useEffect(() => {
54
- setShowSearchCharacter(true);
68
+ setShowSearchCharacterUI(true);
55
69
  }, [activeTab]);
56
70
 
57
71
  const isPrivate = activeTab === 'private';
72
+ const isTrade = activeTab === 'trade';
73
+
74
+ const handlePreviousChatCharacterClick = (
75
+ character: PrivateChatCharacter
76
+ ) => {
77
+ if (!onPreviousChatCharacterClick) return;
78
+ onPreviousChatCharacterClick(character);
79
+ setShowSearchCharacterUI(false);
80
+ };
58
81
 
59
82
  return (
60
83
  <>
@@ -69,29 +92,83 @@ export const ChatRevamp = ({
69
92
  </Tab>
70
93
  ))}
71
94
  </TabContainer>
72
- {isPrivate && showSearchCharacter ? (
73
- <SearchCharacter
74
- onFocus={onFocus}
75
- onBlur={onBlur}
76
- onChangeCharacterName={onChangeCharacterName}
77
- styles={styles}
78
- recentCharacters={privateChatCharacters}
79
- setShowSearchCharacter={setShowSearchCharacter}
80
- onCharacterClick={onCharacterClick}
81
- />
82
- ) : (
83
- <Chat
84
- chatMessages={chatMessages}
85
- onSendChatMessage={
86
- isPrivate ? onSendPrivateChatMessage : onSendGlobalChatMessage
87
- }
88
- sendMessage={true}
89
- onCloseButton={onCloseButton}
90
- styles={styles}
91
- onFocus={onFocus}
92
- onBlur={onBlur}
93
- />
94
- )}
95
+ <PrivateChatContainer
96
+ width={styles?.width || '80%'}
97
+ height={styles?.height || 'auto'}
98
+ >
99
+ <RecentChatTabContainer isPrivate={isPrivate} isOpen={showRecentChats}>
100
+ <RecentChatTopBar isOpen={showRecentChats}>
101
+ <BurgerIconContainer
102
+ onPointerDown={() => setShowRecentChats(t => !t)}
103
+ hasUnseenMessages={unseenMessageCharacterIds?.length > 0 || false}
104
+ >
105
+ <BurgerLineIcon></BurgerLineIcon>
106
+ <BurgerLineIcon></BurgerLineIcon>
107
+ <BurgerLineIcon></BurgerLineIcon>
108
+ </BurgerIconContainer>
109
+ {showRecentChats && (
110
+ <SearchButton
111
+ onPointerDown={() => setShowSearchCharacterUI(true)}
112
+ >
113
+ <RxMagnifyingGlass size={16} color={uiColors.white} />
114
+ </SearchButton>
115
+ )}
116
+ </RecentChatTopBar>
117
+
118
+ <RecentChatLogContainer isOpen={showRecentChats}>
119
+ {recentChatCharacters?.map(character => (
120
+ <ListElementContainer key={character._id}>
121
+ <ListElement
122
+ active={character._id === recentSelectedChatCharacterId}
123
+ onPointerDown={() =>
124
+ handlePreviousChatCharacterClick(character)
125
+ }
126
+ >
127
+ <StatusDot
128
+ isUnseen={
129
+ unseenMessageCharacterIds?.includes(character._id) ||
130
+ false
131
+ }
132
+ />
133
+ {character.name}
134
+ </ListElement>
135
+ <CloseButton
136
+ onPointerDown={() => onRemoveRecentChatCharacter?.(character)}
137
+ >
138
+ <RxCross2 size={16} />
139
+ </CloseButton>
140
+ </ListElementContainer>
141
+ ))}
142
+ </RecentChatLogContainer>
143
+ </RecentChatTabContainer>
144
+ {isPrivate && showSearchCharacterUI ? (
145
+ <SearchCharacter
146
+ onFocus={onFocus}
147
+ onBlur={onBlur}
148
+ onChangeCharacterName={onChangeCharacterName}
149
+ styles={styles}
150
+ recentCharacters={privateChatCharacters}
151
+ setShowSearchCharacter={setShowSearchCharacterUI}
152
+ onCharacterClick={onCharacterClick}
153
+ />
154
+ ) : (
155
+ <Chat
156
+ chatMessages={chatMessages}
157
+ onSendChatMessage={
158
+ isPrivate
159
+ ? onSendPrivateChatMessage
160
+ : isTrade
161
+ ? onSendTradeMessage
162
+ : onSendGlobalChatMessage
163
+ }
164
+ sendMessage={true}
165
+ onCloseButton={onCloseButton}
166
+ styles={styles}
167
+ onFocus={onFocus}
168
+ onBlur={onBlur}
169
+ />
170
+ )}
171
+ </PrivateChatContainer>
95
172
  </>
96
173
  );
97
174
  };
@@ -119,3 +196,136 @@ const Tab = styled.button<{ active: boolean }>`
119
196
  props.active ? uiColors.orange : 'transparent'};
120
197
  color: ${props => (props.active ? 'white' : uiColors.raisinBlack)};
121
198
  `;
199
+
200
+ const PrivateChatContainer = styled.div<{ width: string; height: string }>`
201
+ width: ${({ width }) => width};
202
+ min-height: ${({ height }) => height} !important;
203
+ padding: 10px;
204
+ background-color: rgba(0, 0, 0, 0.2);
205
+ height: auto;
206
+ display: flex;
207
+ gap: 10px;
208
+ `;
209
+
210
+ const RecentChatTabContainer = styled.div<{
211
+ isPrivate: boolean;
212
+ isOpen: boolean;
213
+ }>`
214
+ display: ${props => (props.isPrivate ? 'flex' : 'none')};
215
+ flex-direction: column;
216
+ border-right: 1px solid ${uiColors.gray};
217
+ outline: none;
218
+ width: ${props => (props.isOpen ? '20%' : '30px')} !important;
219
+ transition: width 0.3s ease-in-out;
220
+ overflow: hidden;
221
+
222
+ @media (max-width: 768px) {
223
+ width: ${props => (props.isOpen ? '40%' : '30px')} !important;
224
+ }
225
+ `;
226
+
227
+ const RecentChatTopBar = styled.div<{ isOpen: boolean }>`
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: space-between;
231
+ height: 30px;
232
+ `;
233
+
234
+ const SearchButton = styled.button`
235
+ border: none;
236
+ background-color: transparent;
237
+ display: flex;
238
+ flex-direction: column;
239
+ align-items: flex-end;
240
+ gap: 2px;
241
+ padding: 4px;
242
+ position: relative;
243
+ `;
244
+
245
+ const BurgerIconContainer = styled.button<{ hasUnseenMessages?: boolean }>`
246
+ border: none;
247
+ background-color: transparent;
248
+ display: flex;
249
+ flex-direction: column;
250
+ align-items: flex-end;
251
+ padding: 4px;
252
+ gap: 2px;
253
+ position: relative;
254
+
255
+ &:after {
256
+ content: '';
257
+ width: 6px;
258
+ height: 6px;
259
+ position: absolute;
260
+ top: 0;
261
+ right: 2px;
262
+ border-radius: 50%;
263
+ background-color: ${uiColors.lightGreen};
264
+ display: ${props => (props.hasUnseenMessages ? 'block' : 'none')};
265
+ }
266
+ `;
267
+
268
+ const BurgerLineIcon = styled.span`
269
+ width: 1rem;
270
+ height: 2px;
271
+ background-color: #ffffff;
272
+ `;
273
+
274
+ const RecentChatLogContainer = styled.div<{ isOpen: boolean }>`
275
+ border: none;
276
+ list-style: none;
277
+ display: flex;
278
+ opacity: ${props => (props.isOpen ? 1 : 0)};
279
+ flex-direction: column;
280
+ gap: 0.5rem;
281
+ transition: opacity 0.3s ease-in-out;
282
+ padding: 0;
283
+ margin: 0;
284
+ flex: 1;
285
+ `;
286
+
287
+ const ListElementContainer = styled.div`
288
+ display: flex;
289
+ justify-content: space-between;
290
+ align-items: center;
291
+ `;
292
+
293
+ const ListElement = styled.button<{ active: boolean }>`
294
+ margin: 0.5rem 0 !important;
295
+ font-size: ${uiFonts.size.small} !important;
296
+ padding: 2px;
297
+ all: unset;
298
+ color: ${props => (props.active ? uiColors.yellow : uiColors.white)};
299
+ width: 100%;
300
+ position: relative;
301
+ display: flex;
302
+ align-items: center;
303
+ gap: 4px;
304
+
305
+ &:hover {
306
+ color: #ff0;
307
+ }
308
+ `;
309
+
310
+ const StatusDot = styled.span<{ isUnseen: boolean }>`
311
+ width: 6px;
312
+ height: 6px;
313
+ border-radius: 50%;
314
+ background-color: ${props =>
315
+ props.isUnseen ? uiColors.lightGreen : uiColors.gray};
316
+ display: inline-block;
317
+ margin-right: 6px;
318
+ `;
319
+
320
+ const CloseButton = styled.button`
321
+ all: unset;
322
+ font-size: ${uiFonts.size.xxsmall};
323
+ margin: 0 0.5rem;
324
+ transition: all 0.2s ease-in-out;
325
+ background-color: ${uiColors.red};
326
+ color: ${uiColors.white};
327
+ &:hover {
328
+ background-color: ${uiColors.white};
329
+ color: ${uiColors.red};
330
+ }
331
+ `;
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import { RxMagnifyingGlass } from 'react-icons/rx';
3
3
  import styled from 'styled-components';
4
4
  import { uiColors } from '../../constants/uiColors';
@@ -33,6 +33,17 @@ export const SearchCharacter = ({
33
33
  },
34
34
  }: ISearchCharacterProps) => {
35
35
  const [characterName, setCharacterName] = useState('');
36
+ const searchCharacterRef = useRef<HTMLInputElement>(null);
37
+
38
+ useEffect(() => {
39
+ const timer = setTimeout(() => {
40
+ if (searchCharacterRef.current) {
41
+ searchCharacterRef.current.focus();
42
+ }
43
+ }, 100);
44
+
45
+ return () => clearTimeout(timer);
46
+ }, []);
36
47
 
37
48
  const handleSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
38
49
  event.preventDefault();
@@ -47,34 +58,33 @@ export const SearchCharacter = ({
47
58
  setCharacterName('');
48
59
  onCharacterClick(character);
49
60
  setShowSearchCharacter(false);
50
- };
61
+ };
51
62
 
52
63
  return (
53
- <SearchCharacterContainer
54
- width={styles?.width || '80%'}
55
- height={styles?.height || 'auto'}
56
- >
64
+ <SearchContainer>
57
65
  <Form onSubmit={handleSubmit}>
58
66
  <Column flex={70}>
59
67
  <TextField
60
68
  value={characterName}
61
- id="inputCharacterName"
69
+ ref={searchCharacterRef}
70
+ id="characterName"
71
+ name='characterName'
62
72
  onChange={e => {
63
73
  setCharacterName(e.target.value);
64
74
  onChangeCharacterName(e.target.value);
65
75
  }}
76
+ placeholder='Search for a character...'
66
77
  height={20}
67
78
  type="text"
68
79
  autoComplete="off"
69
80
  onFocus={onFocus}
70
81
  onBlur={onBlur}
71
82
  onPointerDown={onFocus}
72
- autoFocus
73
- placeholder="Type a character name..."
74
- />
83
+ />
75
84
  </Column>
76
85
  <Column justifyContent="flex-end">
77
86
  <SearchButton
87
+ type='submit'
78
88
  buttonColor={styles?.buttonColor || '#005b96'}
79
89
  buttonBackgroundColor={
80
90
  styles?.buttonBackgroundColor || 'rgba(0,0,0,.5)'
@@ -96,27 +106,19 @@ export const SearchCharacter = ({
96
106
  ))}
97
107
  </ListContainer>
98
108
  )}
99
- </SearchCharacterContainer>
109
+ </SearchContainer>
100
110
  );
101
111
  };
102
112
 
103
- interface IContainerProps {
104
- width: string;
105
- height: string;
106
- }
107
113
 
108
114
  interface IButtonProps {
109
115
  buttonColor: string;
110
116
  buttonBackgroundColor: string;
111
117
  }
112
118
 
113
- const SearchCharacterContainer = styled.div<IContainerProps>`
114
- height: ${props => props.height};
115
- width: ${({ width }) => width};
116
- padding: 10px;
117
- background-color: rgba(0, 0, 0, 0.2);
118
- height: auto;
119
- `;
119
+ const SearchContainer = styled.div`
120
+ width: 100%;
121
+ `
120
122
 
121
123
  const Form = styled.form`
122
124
  display: flex;
@@ -150,6 +152,7 @@ const ListContainer = styled.ul`
150
152
  const ListElement = styled.li`
151
153
  margin: 0.5rem 0 !important;
152
154
  font-size: ${uiFonts.size.small};
155
+ padding: 0.5rem 2px;
153
156
 
154
157
  &:hover {
155
158
  color: #ff0;
@@ -66,6 +66,8 @@ type onDragStart =
66
66
  | undefined;
67
67
  type onDragEnd = ((quantity?: number) => void) | undefined;
68
68
 
69
+ const MIN_SLOTS_FOR_SCROLL = 20;
70
+
69
71
  export const ItemContainer: React.FC<IItemContainerProps> = ({
70
72
  itemContainer,
71
73
  onClose,
@@ -241,7 +243,11 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
241
243
  atlasJSON={atlasJSON}
242
244
  />
243
245
  )}
244
- <ItemsContainer className="item-container-body" ref={containerRef}>
246
+ <ItemsContainer
247
+ className="item-container-body"
248
+ ref={containerRef}
249
+ isScrollable={itemContainer.slotQty > MIN_SLOTS_FOR_SCROLL}
250
+ >
245
251
  {onRenderSlots()}
246
252
  </ItemsContainer>
247
253
  </SlotsContainer>
@@ -255,12 +261,16 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
255
261
  );
256
262
  };
257
263
 
258
- const ItemsContainer = styled.div`
264
+ interface IItemsContainerProps {
265
+ isScrollable: boolean;
266
+ }
267
+
268
+ const ItemsContainer = styled.div<IItemsContainerProps>`
259
269
  display: flex;
260
270
  justify-content: center;
261
271
  flex-wrap: wrap;
262
272
  max-height: 270px;
263
- overflow-y: auto;
273
+ overflow-y: ${({ isScrollable }) => (isScrollable ? 'scroll' : 'hidden')};
264
274
  overflow-x: hidden;
265
275
  width: 415px;
266
276
  `;
@@ -76,6 +76,17 @@ export const generateContextMenu = (
76
76
  text: 'Deposit',
77
77
  });
78
78
  }
79
+
80
+ const contextActionMenuDontHaveUseWith = !contextActionMenu.find(action =>
81
+ action.text.toLowerCase().includes('use with')
82
+ );
83
+
84
+ if (item.hasUseWith && contextActionMenuDontHaveUseWith) {
85
+ contextActionMenu.push({
86
+ id: ItemSocketEvents.UseWith,
87
+ text: ItemSocketEvents.UseWith,
88
+ });
89
+ }
79
90
  }
80
91
  if (itemContainerType === ItemContainerType.Equipment) {
81
92
  switch (item.type) {
package/src/index.tsx CHANGED
@@ -32,7 +32,6 @@ export * from './components/RPGUI/RPGUIContainer';
32
32
  export * from './components/RPGUI/RPGUIRoot';
33
33
  export * from './components/RadioButton';
34
34
  export * from './components/RangeSlider';
35
- export * from './components/ShopModal/ShopModal';
36
35
  export * from './components/Shortcuts/Shortcuts';
37
36
  export * from './components/SkillProgressBar';
38
37
  export * from './components/SkillsContainer';
@@ -45,4 +44,3 @@ export * from './components/itemSelector/ItemSelector';
45
44
  export * from './components/shared/SpriteFromAtlas';
46
45
  export * from './components/typography/DynamicText';
47
46
  export { useEventListener } from './hooks/useEventListener';
48
-
@@ -5,7 +5,7 @@ import {
5
5
  ItemSlotType,
6
6
  ItemSubType,
7
7
  ItemType,
8
- UserAccountTypes
8
+ UserAccountTypes,
9
9
  } from '@rpg-engine/shared';
10
10
 
11
11
  export const items: IItem[] = [
@@ -586,7 +586,7 @@ export const itemContainerMock = (
586
586
  _id: '629ba0b6fe3f43002f58f23b',
587
587
  name: 'Item Container',
588
588
  owner: '629ba0b6fe3f43002f58f23b',
589
- slotQty: 60,
589
+ slotQty: 20,
590
590
  slots: {
591
591
  0: items[0],
592
592
  1: items[1],
@@ -614,4 +614,4 @@ export const itemContainerMock = (
614
614
  ...props,
615
615
  };
616
616
  }
617
- }
617
+ };
@@ -202,6 +202,7 @@ const chatMessagesMock = [
202
202
  const tabsMock = [
203
203
  { label: 'Global', id: 'global' },
204
204
  { label: 'Private', id: 'private' },
205
+ { label: 'Trade', id: 'trade' },
205
206
  ];
206
207
 
207
208
  const recentPrivateChatCharactersMock = [
@@ -221,7 +222,6 @@ Default.args = {
221
222
  onSendGlobalChatMessage: () => {},
222
223
  onChangeCharacterName: () => {},
223
224
  chatMessages: chatMessagesMock,
224
- opacity: 0.5,
225
225
  styles: { width: `calc(100% - 0.5rem * 2)`, height: '200px' },
226
226
  onCloseButton: () => console.log('closing chat...'),
227
227
  tabs: tabsMock,
@@ -229,15 +229,15 @@ Default.args = {
229
229
  activeTab: 'global',
230
230
  onChangeTab: () => {},
231
231
  onSendPrivateChatMessage: () => {},
232
+ onSendTradeMessage: () => {},
232
233
  };
233
234
 
234
- export const PrivateCharacters = Template.bind({});
235
+ export const Private = Template.bind({});
235
236
 
236
- PrivateCharacters.args = {
237
+ Private.args = {
237
238
  onSendGlobalChatMessage: () => {},
238
239
  onChangeCharacterName: () => {},
239
240
  chatMessages: chatMessagesMock,
240
- opacity: 0.5,
241
241
  styles: { width: `calc(100% - 0.5rem * 2)`, height: '200px' },
242
242
  onCloseButton: () => {},
243
243
  tabs: tabsMock,
@@ -245,4 +245,23 @@ PrivateCharacters.args = {
245
245
  activeTab: 'private',
246
246
  onChangeTab: () => {},
247
247
  onSendPrivateChatMessage: () => {},
248
+ recentChatCharacters: recentPrivateChatCharactersMock,
249
+ recentSelectedChatCharacterId: recentPrivateChatCharactersMock[0]._id,
250
+ unseenMessageCharacterIds: [recentPrivateChatCharactersMock[0]._id],
251
+ onSendTradeMessage: () => {},
252
+ };
253
+
254
+ export const Trade = Template.bind({});
255
+
256
+ Trade.args = {
257
+ onSendGlobalChatMessage: () => {},
258
+ onChangeCharacterName: () => {},
259
+ chatMessages: chatMessagesMock,
260
+ styles: { width: `calc(100% - 0.5rem * 2)`, height: '200px' },
261
+ onCloseButton: () => {},
262
+ tabs: tabsMock,
263
+ privateChatCharacters: recentPrivateChatCharactersMock,
264
+ activeTab: 'trade',
265
+ onChangeTab: () => {},
266
+ onSendTradeMessage: () => {},
248
267
  };