@rpg-engine/long-bow 0.7.19 → 0.7.21
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 +1 -0
- package/dist/components/ChatRevamp/ChatRevamp.d.ts +1 -0
- package/dist/long-bow.cjs.development.js +95 -40
- 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 +95 -40
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Chat/Chat.tsx +44 -38
- package/src/components/ChatRevamp/ChatRevamp.tsx +96 -14
package/package.json
CHANGED
|
@@ -28,6 +28,7 @@ export interface IChatProps {
|
|
|
28
28
|
opacity?: number;
|
|
29
29
|
sendMessage: boolean;
|
|
30
30
|
styles?: IStyles;
|
|
31
|
+
isExpanded: boolean;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export const Chat: React.FC<IChatProps> = ({
|
|
@@ -43,15 +44,17 @@ export const Chat: React.FC<IChatProps> = ({
|
|
|
43
44
|
width: '100%',
|
|
44
45
|
height: '100%',
|
|
45
46
|
},
|
|
47
|
+
isExpanded,
|
|
46
48
|
}) => {
|
|
47
49
|
const [message, setMessage] = useState('');
|
|
48
50
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
49
51
|
|
|
50
52
|
useEffect(() => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
if (isExpanded) {
|
|
54
|
+
scrollChatToBottom();
|
|
55
|
+
}
|
|
53
56
|
inputRef.current?.focus();
|
|
54
|
-
}, [chatMessages]);
|
|
57
|
+
}, [chatMessages, isExpanded]);
|
|
55
58
|
|
|
56
59
|
const scrollChatToBottom = () => {
|
|
57
60
|
const scrollingElement = document.querySelector('.chat-body');
|
|
@@ -81,39 +84,41 @@ export const Chat: React.FC<IChatProps> = ({
|
|
|
81
84
|
<ChatContainer
|
|
82
85
|
width={styles.width || 'auto'}
|
|
83
86
|
height={styles.height || 'auto'}
|
|
87
|
+
isExpanded={isExpanded}
|
|
84
88
|
>
|
|
85
|
-
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
89
|
+
{isExpanded && (
|
|
90
|
+
<ErrorBoundary fallback={<p>Oops! Your chat has crashed.</p>}>
|
|
91
|
+
<CloseButton onClick={onCloseButton}>
|
|
92
|
+
<FaTimes />
|
|
93
|
+
</CloseButton>
|
|
94
|
+
<MessagesContainer className="chat-body">
|
|
95
|
+
{chatMessages.map((chatMessage, index) => (
|
|
96
|
+
<Message
|
|
97
|
+
color={styles.textColor || uiColors.yellow}
|
|
98
|
+
key={`${chatMessage._id}_${index}`}
|
|
99
|
+
>
|
|
100
|
+
{formatMessage(chatMessage)}
|
|
101
|
+
</Message>
|
|
102
|
+
))}
|
|
103
|
+
</MessagesContainer>
|
|
104
|
+
</ErrorBoundary>
|
|
105
|
+
)}
|
|
106
|
+
<Form onSubmit={handleSubmit} isExpanded={isExpanded}>
|
|
107
|
+
<TextField
|
|
108
|
+
ref={inputRef}
|
|
109
|
+
value={message}
|
|
110
|
+
onChange={e => setMessage(e.target.value)}
|
|
111
|
+
type="text"
|
|
112
|
+
autoComplete="off"
|
|
113
|
+
onFocus={onFocus}
|
|
114
|
+
onBlur={onBlur}
|
|
115
|
+
onPointerDown={onFocus}
|
|
116
|
+
placeholder="Type your message..."
|
|
117
|
+
/>
|
|
118
|
+
<SendButton type="submit" disabled={!message.trim()}>
|
|
119
|
+
▶
|
|
120
|
+
</SendButton>
|
|
121
|
+
</Form>
|
|
117
122
|
</ChatContainer>
|
|
118
123
|
);
|
|
119
124
|
};
|
|
@@ -127,9 +132,9 @@ interface IMessageProps {
|
|
|
127
132
|
color: string;
|
|
128
133
|
}
|
|
129
134
|
|
|
130
|
-
const ChatContainer = styled.div<IContainerProps>`
|
|
135
|
+
const ChatContainer = styled.div<IContainerProps & { isExpanded: boolean }>`
|
|
131
136
|
width: ${props => props.width};
|
|
132
|
-
height: ${props => props.height};
|
|
137
|
+
height: ${props => (props.isExpanded ? props.height : 'auto')};
|
|
133
138
|
background-color: rgba(30, 30, 30, 0.3);
|
|
134
139
|
display: flex;
|
|
135
140
|
flex-direction: column;
|
|
@@ -183,10 +188,11 @@ const Message = styled.div<IMessageProps>`
|
|
|
183
188
|
word-break: break-word;
|
|
184
189
|
`;
|
|
185
190
|
|
|
186
|
-
const Form = styled.form
|
|
191
|
+
const Form = styled.form<{ isExpanded: boolean }>`
|
|
187
192
|
display: flex;
|
|
188
193
|
padding: 8px;
|
|
189
194
|
background-color: rgba(42, 42, 42, 0.4);
|
|
195
|
+
border-radius: ${props => (props.isExpanded ? '0' : '8px')};
|
|
190
196
|
`;
|
|
191
197
|
|
|
192
198
|
const TextField = styled.input`
|
|
@@ -4,9 +4,10 @@ import {
|
|
|
4
4
|
IPrivateChatMessage,
|
|
5
5
|
ITradeChatMessage,
|
|
6
6
|
} from '@rpg-engine/shared';
|
|
7
|
-
import React, { useState } from 'react';
|
|
7
|
+
import React, { useEffect, useState } from 'react';
|
|
8
|
+
import { IoMdContract, IoMdExpand } from 'react-icons/io';
|
|
8
9
|
import { RxCross2, RxMagnifyingGlass } from 'react-icons/rx';
|
|
9
|
-
import styled from 'styled-components';
|
|
10
|
+
import styled, { css } from 'styled-components';
|
|
10
11
|
import { uiColors } from '../../constants/uiColors';
|
|
11
12
|
import { uiFonts } from '../../constants/uiFonts';
|
|
12
13
|
import { Chat, IStyles } from '../Chat/Chat';
|
|
@@ -42,6 +43,7 @@ export interface IChatRevampProps {
|
|
|
42
43
|
searchCharacterUI: boolean;
|
|
43
44
|
hideSearchCharacterUI: () => void;
|
|
44
45
|
showSearchCharacterUI: () => void;
|
|
46
|
+
minimizedByDefault?: boolean;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
export const ChatRevamp: React.FC<IChatRevampProps> = ({
|
|
@@ -67,14 +69,31 @@ export const ChatRevamp: React.FC<IChatRevampProps> = ({
|
|
|
67
69
|
searchCharacterUI,
|
|
68
70
|
hideSearchCharacterUI,
|
|
69
71
|
showSearchCharacterUI,
|
|
72
|
+
minimizedByDefault = false,
|
|
70
73
|
}) => {
|
|
71
74
|
const [showRecentChats, setShowRecentChats] = useState(false);
|
|
75
|
+
const [isExpanded, setIsExpanded] = useState(!minimizedByDefault);
|
|
72
76
|
|
|
73
77
|
const isPrivate = activeTab === 'private';
|
|
74
78
|
const isTrade = activeTab === 'trade';
|
|
75
79
|
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (isPrivate) {
|
|
82
|
+
setIsExpanded(true);
|
|
83
|
+
}
|
|
84
|
+
}, [isPrivate]);
|
|
85
|
+
|
|
86
|
+
const toggleExpand = () => setIsExpanded(prev => !prev);
|
|
87
|
+
|
|
76
88
|
const toggleRecentChats = () => setShowRecentChats(prev => !prev);
|
|
77
89
|
|
|
90
|
+
const handleTabChange = (tabId: string) => {
|
|
91
|
+
if (tabId === 'private') {
|
|
92
|
+
setIsExpanded(true);
|
|
93
|
+
}
|
|
94
|
+
onChangeTab(tabId);
|
|
95
|
+
};
|
|
96
|
+
|
|
78
97
|
const handlePreviousChatCharacterClick = (
|
|
79
98
|
character: PrivateChatCharacter
|
|
80
99
|
) => {
|
|
@@ -88,7 +107,7 @@ export const ChatRevamp: React.FC<IChatRevampProps> = ({
|
|
|
88
107
|
<Tab
|
|
89
108
|
key={`${tab.label}_${index}`}
|
|
90
109
|
active={tab.id === activeTab}
|
|
91
|
-
onPointerDown={() =>
|
|
110
|
+
onPointerDown={() => handleTabChange(tab.id)}
|
|
92
111
|
>
|
|
93
112
|
{tab.label}
|
|
94
113
|
</Tab>
|
|
@@ -170,31 +189,67 @@ export const ChatRevamp: React.FC<IChatRevampProps> = ({
|
|
|
170
189
|
styles={styles}
|
|
171
190
|
onFocus={onFocus}
|
|
172
191
|
onBlur={onBlur}
|
|
192
|
+
isExpanded={isExpanded}
|
|
173
193
|
/>
|
|
174
194
|
);
|
|
175
195
|
};
|
|
176
196
|
|
|
177
197
|
return (
|
|
178
|
-
|
|
179
|
-
{
|
|
198
|
+
<ChatRevampContainer>
|
|
199
|
+
<TopBar isExpanded={isExpanded}>
|
|
200
|
+
{isExpanded && renderTabs()}
|
|
201
|
+
<ExpandButton onClick={toggleExpand} isExpanded={isExpanded}>
|
|
202
|
+
{isExpanded ? <IoMdContract size={20} /> : <IoMdExpand size={20} />}
|
|
203
|
+
</ExpandButton>
|
|
204
|
+
</TopBar>
|
|
180
205
|
<PrivateChatContainer
|
|
181
206
|
width={styles?.width || '80%'}
|
|
182
207
|
height={styles?.height || 'auto'}
|
|
208
|
+
isExpanded={isExpanded}
|
|
183
209
|
>
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
210
|
+
{isExpanded && (
|
|
211
|
+
<RecentChatTabContainer
|
|
212
|
+
isPrivate={isPrivate}
|
|
213
|
+
isOpen={showRecentChats}
|
|
214
|
+
>
|
|
215
|
+
{renderRecentChatTopBar()}
|
|
216
|
+
{renderRecentChatList()}
|
|
217
|
+
</RecentChatTabContainer>
|
|
218
|
+
)}
|
|
188
219
|
<ChatWrapper>{renderChatContent()}</ChatWrapper>
|
|
189
220
|
</PrivateChatContainer>
|
|
190
|
-
|
|
221
|
+
</ChatRevampContainer>
|
|
191
222
|
);
|
|
192
223
|
};
|
|
193
224
|
|
|
194
|
-
const
|
|
225
|
+
const ChatRevampContainer = styled.div`
|
|
226
|
+
display: flex;
|
|
227
|
+
flex-direction: column;
|
|
195
228
|
width: 100%;
|
|
229
|
+
position: relative;
|
|
230
|
+
`;
|
|
231
|
+
|
|
232
|
+
interface ITopBarProps {
|
|
233
|
+
isExpanded: boolean;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const TopBar = styled.div<ITopBarProps>`
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
justify-content: flex-start;
|
|
240
|
+
|
|
241
|
+
${({ isExpanded }) =>
|
|
242
|
+
!isExpanded &&
|
|
243
|
+
css`
|
|
244
|
+
min-height: 32px; // Ensure there's always space for the expand button when its collapsed
|
|
245
|
+
`}
|
|
246
|
+
`;
|
|
247
|
+
|
|
248
|
+
const TabContainer = styled.div`
|
|
196
249
|
display: flex;
|
|
197
250
|
gap: 10px;
|
|
251
|
+
align-items: center;
|
|
252
|
+
flex-grow: 1;
|
|
198
253
|
`;
|
|
199
254
|
|
|
200
255
|
const Tab = styled.button<{ active: boolean }>`
|
|
@@ -216,14 +271,40 @@ const Tab = styled.button<{ active: boolean }>`
|
|
|
216
271
|
color: ${props => (props.active ? 'white' : uiColors.darkGray)};
|
|
217
272
|
`;
|
|
218
273
|
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
274
|
+
const ExpandButton = styled.button<{ isExpanded: boolean }>`
|
|
275
|
+
position: absolute;
|
|
276
|
+
top: 0;
|
|
277
|
+
right: 0;
|
|
278
|
+
width: 30px;
|
|
279
|
+
height: 30px;
|
|
280
|
+
background-color: ${uiColors.orange};
|
|
281
|
+
color: white;
|
|
282
|
+
border: none;
|
|
283
|
+
border-radius: 50%;
|
|
284
|
+
display: flex;
|
|
285
|
+
justify-content: center;
|
|
286
|
+
align-items: center;
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
transition: all 0.3s ease;
|
|
289
|
+
z-index: 10;
|
|
290
|
+
|
|
291
|
+
&:hover {
|
|
292
|
+
background-color: ${uiColors.orange};
|
|
293
|
+
}
|
|
294
|
+
`;
|
|
222
295
|
|
|
296
|
+
const PrivateChatContainer = styled.div<{
|
|
297
|
+
width: string;
|
|
298
|
+
height: string;
|
|
299
|
+
isExpanded: boolean;
|
|
300
|
+
}>`
|
|
301
|
+
width: ${({ width }) => width};
|
|
302
|
+
height: ${({ height, isExpanded }) => (isExpanded ? height : 'auto')};
|
|
223
303
|
padding: 10px;
|
|
224
304
|
background-color: rgba(0, 0, 0, 0.2);
|
|
225
305
|
display: flex;
|
|
226
306
|
gap: 10px;
|
|
307
|
+
flex-direction: column;
|
|
227
308
|
`;
|
|
228
309
|
|
|
229
310
|
const RecentChatTabContainer = styled.div<{
|
|
@@ -394,4 +475,5 @@ const ChatWrapper = styled.div`
|
|
|
394
475
|
overflow: hidden;
|
|
395
476
|
display: flex;
|
|
396
477
|
flex-direction: column;
|
|
478
|
+
position: relative;
|
|
397
479
|
`;
|