@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.
- package/dist/components/Chat/Chat.d.ts +6 -2
- package/dist/components/ChatRevamp/ChatRevamp.d.ts +10 -8
- package/dist/index.d.ts +0 -1
- package/dist/long-bow.cjs.development.js +222 -135
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +224 -136
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/stories/ChatRevamp.stories.d.ts +2 -1
- package/package.json +2 -2
- package/src/components/Chat/Chat.tsx +11 -16
- package/src/components/ChatRevamp/ChatRevamp.tsx +242 -32
- package/src/components/ChatRevamp/SearchCharacter.tsx +25 -22
- package/src/components/Item/Inventory/ItemContainer.tsx +13 -3
- package/src/components/Item/Inventory/itemContainerHelper.ts +11 -0
- package/src/index.tsx +0 -2
- package/src/mocks/itemContainer.mocks.ts +3 -3
- package/src/stories/ChatRevamp.stories.tsx +23 -4
|
@@ -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
|
|
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.
|
|
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.
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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 [
|
|
64
|
+
const [showSearchCharacterUI, setShowSearchCharacterUI] = useState(true);
|
|
65
|
+
const [showRecentChats, setShowRecentChats] = useState(false);
|
|
52
66
|
|
|
53
67
|
useEffect(() => {
|
|
54
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
<
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
|
235
|
+
export const Private = Template.bind({});
|
|
235
236
|
|
|
236
|
-
|
|
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
|
};
|