@rpg-engine/long-bow 0.7.19 → 0.7.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.7.19",
3
+ "version": "0.7.22",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -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
- scrollChatToBottom();
52
- // Focus the input element when the component mounts
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
- <CloseButton onClick={onCloseButton}>
86
- <FaTimes />
87
- </CloseButton>
88
- <ErrorBoundary fallback={<p>Oops! Your chat has crashed.</p>}>
89
- <MessagesContainer className="chat-body">
90
- {chatMessages.map((chatMessage, index) => (
91
- <Message
92
- color={styles.textColor || uiColors.yellow}
93
- key={`${chatMessage._id}_${index}`}
94
- >
95
- {formatMessage(chatMessage)}
96
- </Message>
97
- ))}
98
- </MessagesContainer>
99
-
100
- <Form onSubmit={handleSubmit}>
101
- <TextField
102
- ref={inputRef}
103
- value={message}
104
- onChange={e => setMessage(e.target.value)}
105
- type="text"
106
- autoComplete="off"
107
- onFocus={onFocus}
108
- onBlur={onBlur}
109
- onPointerDown={onFocus}
110
- placeholder="Type your message..."
111
- />
112
- <SendButton type="submit" disabled={!message.trim()}>
113
-
114
- </SendButton>
115
- </Form>
116
- </ErrorBoundary>
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,8 @@ export interface IChatRevampProps {
42
43
  searchCharacterUI: boolean;
43
44
  hideSearchCharacterUI: () => void;
44
45
  showSearchCharacterUI: () => void;
46
+ minimizedByDefault?: boolean;
47
+ autoCloseOnSend?: boolean;
45
48
  }
46
49
 
47
50
  export const ChatRevamp: React.FC<IChatRevampProps> = ({
@@ -67,14 +70,32 @@ export const ChatRevamp: React.FC<IChatRevampProps> = ({
67
70
  searchCharacterUI,
68
71
  hideSearchCharacterUI,
69
72
  showSearchCharacterUI,
73
+ minimizedByDefault = false,
74
+ autoCloseOnSend = false,
70
75
  }) => {
71
76
  const [showRecentChats, setShowRecentChats] = useState(false);
77
+ const [isExpanded, setIsExpanded] = useState(!minimizedByDefault);
72
78
 
73
79
  const isPrivate = activeTab === 'private';
74
80
  const isTrade = activeTab === 'trade';
75
81
 
82
+ useEffect(() => {
83
+ if (isPrivate) {
84
+ setIsExpanded(true);
85
+ }
86
+ }, [isPrivate]);
87
+
88
+ const toggleExpand = () => setIsExpanded(prev => !prev);
89
+
76
90
  const toggleRecentChats = () => setShowRecentChats(prev => !prev);
77
91
 
92
+ const handleTabChange = (tabId: string) => {
93
+ if (tabId === 'private') {
94
+ setIsExpanded(true);
95
+ }
96
+ onChangeTab(tabId);
97
+ };
98
+
78
99
  const handlePreviousChatCharacterClick = (
79
100
  character: PrivateChatCharacter
80
101
  ) => {
@@ -88,7 +109,7 @@ export const ChatRevamp: React.FC<IChatRevampProps> = ({
88
109
  <Tab
89
110
  key={`${tab.label}_${index}`}
90
111
  active={tab.id === activeTab}
91
- onPointerDown={() => onChangeTab(tab.id)}
112
+ onPointerDown={() => handleTabChange(tab.id)}
92
113
  >
93
114
  {tab.label}
94
115
  </Tab>
@@ -158,43 +179,85 @@ export const ChatRevamp: React.FC<IChatRevampProps> = ({
158
179
  return (
159
180
  <Chat
160
181
  chatMessages={chatMessages}
161
- onSendChatMessage={
162
- isPrivate
163
- ? onSendPrivateChatMessage
164
- : isTrade
165
- ? onSendTradeMessage
166
- : onSendGlobalChatMessage
167
- }
182
+ onSendChatMessage={() => {
183
+ if (autoCloseOnSend) {
184
+ onCloseButton();
185
+ }
186
+
187
+ if (isPrivate) {
188
+ return onSendPrivateChatMessage;
189
+ } else if (isTrade) {
190
+ return onSendTradeMessage;
191
+ } else {
192
+ return onSendGlobalChatMessage;
193
+ }
194
+ }}
168
195
  sendMessage={true}
169
196
  onCloseButton={onCloseButton}
170
197
  styles={styles}
171
198
  onFocus={onFocus}
172
199
  onBlur={onBlur}
200
+ isExpanded={isExpanded}
173
201
  />
174
202
  );
175
203
  };
176
204
 
177
205
  return (
178
- <>
179
- {renderTabs()}
206
+ <ChatRevampContainer>
207
+ <TopBar isExpanded={isExpanded}>
208
+ {isExpanded && renderTabs()}
209
+ <ExpandButton onClick={toggleExpand} isExpanded={isExpanded}>
210
+ {isExpanded ? <IoMdContract size={20} /> : <IoMdExpand size={20} />}
211
+ </ExpandButton>
212
+ </TopBar>
180
213
  <PrivateChatContainer
181
214
  width={styles?.width || '80%'}
182
215
  height={styles?.height || 'auto'}
216
+ isExpanded={isExpanded}
183
217
  >
184
- <RecentChatTabContainer isPrivate={isPrivate} isOpen={showRecentChats}>
185
- {renderRecentChatTopBar()}
186
- {renderRecentChatList()}
187
- </RecentChatTabContainer>
218
+ {isExpanded && (
219
+ <RecentChatTabContainer
220
+ isPrivate={isPrivate}
221
+ isOpen={showRecentChats}
222
+ >
223
+ {renderRecentChatTopBar()}
224
+ {renderRecentChatList()}
225
+ </RecentChatTabContainer>
226
+ )}
188
227
  <ChatWrapper>{renderChatContent()}</ChatWrapper>
189
228
  </PrivateChatContainer>
190
- </>
229
+ </ChatRevampContainer>
191
230
  );
192
231
  };
193
232
 
194
- const TabContainer = styled.div`
233
+ const ChatRevampContainer = styled.div`
234
+ display: flex;
235
+ flex-direction: column;
195
236
  width: 100%;
237
+ position: relative;
238
+ `;
239
+
240
+ interface ITopBarProps {
241
+ isExpanded: boolean;
242
+ }
243
+
244
+ const TopBar = styled.div<ITopBarProps>`
245
+ display: flex;
246
+ align-items: center;
247
+ justify-content: flex-start;
248
+
249
+ ${({ isExpanded }) =>
250
+ !isExpanded &&
251
+ css`
252
+ min-height: 32px; // Ensure there's always space for the expand button when its collapsed
253
+ `}
254
+ `;
255
+
256
+ const TabContainer = styled.div`
196
257
  display: flex;
197
258
  gap: 10px;
259
+ align-items: center;
260
+ flex-grow: 1;
198
261
  `;
199
262
 
200
263
  const Tab = styled.button<{ active: boolean }>`
@@ -216,14 +279,40 @@ const Tab = styled.button<{ active: boolean }>`
216
279
  color: ${props => (props.active ? 'white' : uiColors.darkGray)};
217
280
  `;
218
281
 
219
- const PrivateChatContainer = styled.div<{ width: string; height: string }>`
220
- width: ${({ width }) => width};
221
- height: ${({ height }) => height};
282
+ const ExpandButton = styled.button<{ isExpanded: boolean }>`
283
+ position: absolute;
284
+ top: 0;
285
+ ${({ isExpanded }) => (isExpanded ? 'right: 0' : 'left: 0')};
286
+ width: 30px;
287
+ height: 30px;
288
+ background-color: ${uiColors.orange};
289
+ color: white;
290
+ border: none;
291
+ border-radius: 50%;
292
+ display: flex;
293
+ justify-content: center;
294
+ align-items: center;
295
+ cursor: pointer;
296
+ transition: all 0.3s ease;
297
+ z-index: 10;
222
298
 
299
+ &:hover {
300
+ background-color: ${uiColors.orange};
301
+ }
302
+ `;
303
+
304
+ const PrivateChatContainer = styled.div<{
305
+ width: string;
306
+ height: string;
307
+ isExpanded: boolean;
308
+ }>`
309
+ width: ${({ width }) => width};
310
+ height: ${({ height, isExpanded }) => (isExpanded ? height : 'auto')};
223
311
  padding: 10px;
224
312
  background-color: rgba(0, 0, 0, 0.2);
225
313
  display: flex;
226
314
  gap: 10px;
315
+ flex-wrap: wrap;
227
316
  `;
228
317
 
229
318
  const RecentChatTabContainer = styled.div<{
@@ -394,4 +483,5 @@ const ChatWrapper = styled.div`
394
483
  overflow: hidden;
395
484
  display: flex;
396
485
  flex-direction: column;
486
+ position: relative;
397
487
  `;