@rpg-engine/long-bow 0.8.27 → 0.8.29
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/long-bow.cjs.development.js +42 -69
- 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 +42 -69
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/InformationCenter/InformationCenter.tsx +5 -19
- package/src/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.tsx +26 -28
- package/src/components/InformationCenter/sections/bestiary/InformationCenterNPCDetails.tsx +31 -7
- package/src/components/InformationCenter/sections/items/InformationCenterItemsSection.tsx +26 -21
- package/src/components/InformationCenter/shared/BaseInformationDetails.tsx +34 -11
- package/src/components/shared/Collapsible/Collapsible.tsx +1 -1
package/package.json
CHANGED
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
} from '@rpg-engine/shared';
|
|
10
10
|
import { DraggableContainer } from '../DraggableContainer';
|
|
11
11
|
import { InternalTabs } from '../InternalTabs/InternalTabs';
|
|
12
|
+
import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';
|
|
12
13
|
import { InformationCenterBestiarySection } from './sections/bestiary/InformationCenterBestiarySection';
|
|
13
14
|
import { InformationCenterFAQSection } from './sections/faq/InformationCenterFaqSection';
|
|
14
|
-
import { InformationCenterItemDetails } from './sections/items/InformationCenterItemDetails';
|
|
15
15
|
import { InformationCenterItemsSection } from './sections/items/InformationCenterItemsSection';
|
|
16
16
|
import { InformationCenterTutorialsSection } from './sections/tutorials/InformationCenterTutorialsSection';
|
|
17
17
|
|
|
@@ -47,10 +47,6 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
|
|
|
47
47
|
initialSearchQuery = '',
|
|
48
48
|
}) => {
|
|
49
49
|
const [activeTab, setActiveTab] = useState('bestiary');
|
|
50
|
-
const [
|
|
51
|
-
selectedItem,
|
|
52
|
-
setSelectedItem,
|
|
53
|
-
] = useState<IInformationCenterItem | null>(null);
|
|
54
50
|
|
|
55
51
|
if (loading) {
|
|
56
52
|
return <LoadingMessage>Loading...</LoadingMessage>;
|
|
@@ -117,7 +113,10 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
|
|
|
117
113
|
];
|
|
118
114
|
|
|
119
115
|
return (
|
|
120
|
-
<DraggableContainer
|
|
116
|
+
<DraggableContainer
|
|
117
|
+
title="Information Center"
|
|
118
|
+
type={RPGUIContainerTypes.Framed}
|
|
119
|
+
>
|
|
121
120
|
<Container>
|
|
122
121
|
<InternalTabs
|
|
123
122
|
tabs={tabs}
|
|
@@ -129,19 +128,6 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
|
|
|
129
128
|
borderColor="#f59e0b"
|
|
130
129
|
hoverColor="#fef3c7"
|
|
131
130
|
/>
|
|
132
|
-
{selectedItem && (
|
|
133
|
-
<InformationCenterItemDetails
|
|
134
|
-
item={selectedItem}
|
|
135
|
-
itemsAtlasJSON={itemsAtlasJSON}
|
|
136
|
-
itemsAtlasIMG={itemsAtlasIMG}
|
|
137
|
-
droppedBy={bestiaryItems.filter(npc =>
|
|
138
|
-
npc.loots?.some(
|
|
139
|
-
loot => loot.itemBlueprintKey === selectedItem.key
|
|
140
|
-
)
|
|
141
|
-
)}
|
|
142
|
-
onBack={() => setSelectedItem(null)}
|
|
143
|
-
/>
|
|
144
|
-
)}
|
|
145
131
|
</Container>
|
|
146
132
|
</DraggableContainer>
|
|
147
133
|
);
|
package/src/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.tsx
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IInformationCenterNPC,
|
|
3
|
+
NPCAlignment,
|
|
4
|
+
isMobileOrTablet,
|
|
5
|
+
} from '@rpg-engine/shared';
|
|
2
6
|
import React, { useMemo, useState } from 'react';
|
|
3
7
|
import styled from 'styled-components';
|
|
4
8
|
import { IOptionsProps } from '../../../Dropdown';
|
|
@@ -8,6 +12,7 @@ import { InformationCenterCell } from '../../InformationCenterCell';
|
|
|
8
12
|
import { formatItemType } from '../items/InformationCenterItemsSection';
|
|
9
13
|
import { InformationCenterNPCDetails } from './InformationCenterNPCDetails';
|
|
10
14
|
import { InformationCenterNPCTooltip } from './InformationCenterNPCTooltip';
|
|
15
|
+
|
|
11
16
|
interface IBestiarySectionProps {
|
|
12
17
|
bestiaryItems: IInformationCenterNPC[];
|
|
13
18
|
itemsAtlasJSON: Record<string, any>;
|
|
@@ -31,6 +36,7 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
31
36
|
initialSearchQuery,
|
|
32
37
|
tabId,
|
|
33
38
|
}) => {
|
|
39
|
+
const isMobile = isMobileOrTablet();
|
|
34
40
|
const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
|
|
35
41
|
const [tooltipData, setTooltipData] = useState<{
|
|
36
42
|
npc: IInformationCenterNPC;
|
|
@@ -40,13 +46,12 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
40
46
|
selectedMonster,
|
|
41
47
|
setSelectedMonster,
|
|
42
48
|
] = useState<IInformationCenterNPC | null>(null);
|
|
43
|
-
const [isTouchDevice] = useState('ontouchstart' in window);
|
|
44
49
|
|
|
45
50
|
const handleMouseEnter = (
|
|
46
51
|
monster: IInformationCenterNPC,
|
|
47
52
|
event: React.MouseEvent
|
|
48
53
|
) => {
|
|
49
|
-
if (!
|
|
54
|
+
if (!isMobile && !selectedMonster) {
|
|
50
55
|
setTooltipData({
|
|
51
56
|
npc: monster,
|
|
52
57
|
position: { x: event.clientX, y: event.clientY },
|
|
@@ -55,13 +60,13 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
const handleMouseLeave = () => {
|
|
58
|
-
if (!
|
|
63
|
+
if (!isMobile) {
|
|
59
64
|
setTooltipData(null);
|
|
60
65
|
}
|
|
61
66
|
};
|
|
62
67
|
|
|
63
68
|
const handleMouseMove = (event: React.MouseEvent) => {
|
|
64
|
-
if (!
|
|
69
|
+
if (!isMobile && tooltipData) {
|
|
65
70
|
setTooltipData({
|
|
66
71
|
...tooltipData,
|
|
67
72
|
position: { x: event.clientX, y: event.clientY },
|
|
@@ -73,18 +78,9 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
73
78
|
monster: IInformationCenterNPC,
|
|
74
79
|
event: React.TouchEvent
|
|
75
80
|
) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (tooltipData?.npc.id === monster.id) {
|
|
80
|
-
setTooltipData(null);
|
|
81
|
-
} else {
|
|
82
|
-
setTooltipData({
|
|
83
|
-
npc: monster,
|
|
84
|
-
position: { x: touch.clientX, y: touch.clientY },
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
setSelectedMonster(monster);
|
|
83
|
+
setTooltipData(null);
|
|
88
84
|
};
|
|
89
85
|
|
|
90
86
|
const handleMonsterClick = (monster: IInformationCenterNPC) => {
|
|
@@ -170,7 +166,7 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
170
166
|
dependencies={[selectedBestiaryCategory]}
|
|
171
167
|
itemHeight="180px"
|
|
172
168
|
/>
|
|
173
|
-
{tooltipData && (
|
|
169
|
+
{!isMobile && tooltipData && (
|
|
174
170
|
<Portal>
|
|
175
171
|
<TooltipWrapper
|
|
176
172
|
style={{
|
|
@@ -188,16 +184,18 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
188
184
|
</Portal>
|
|
189
185
|
)}
|
|
190
186
|
{selectedMonster && (
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
187
|
+
<Portal>
|
|
188
|
+
<InformationCenterNPCDetails
|
|
189
|
+
npc={selectedMonster}
|
|
190
|
+
itemsAtlasJSON={itemsAtlasJSON}
|
|
191
|
+
itemsAtlasIMG={itemsAtlasIMG}
|
|
192
|
+
iconAtlasIMG={iconsAtlasIMG}
|
|
193
|
+
iconAtlasJSON={iconsAtlasJSON}
|
|
194
|
+
entitiesAtlasJSON={entitiesAtlasJSON}
|
|
195
|
+
entitiesAtlasIMG={entitiesAtlasIMG}
|
|
196
|
+
onBack={() => setSelectedMonster(null)}
|
|
197
|
+
/>
|
|
198
|
+
</Portal>
|
|
201
199
|
)}
|
|
202
200
|
</>
|
|
203
201
|
);
|
|
@@ -265,9 +265,11 @@ const Value = styled.span`
|
|
|
265
265
|
const StyledCollapsible = styled(Collapsible)`
|
|
266
266
|
background: rgba(255, 255, 255, 0.05);
|
|
267
267
|
border-radius: 4px;
|
|
268
|
-
overflow:
|
|
268
|
+
overflow: visible;
|
|
269
269
|
scrollbar-width: thin;
|
|
270
270
|
scrollbar-color: ${uiColors.darkGray} transparent;
|
|
271
|
+
width: 100%;
|
|
272
|
+
box-sizing: border-box;
|
|
271
273
|
`;
|
|
272
274
|
|
|
273
275
|
const StatGrid = styled.div`
|
|
@@ -354,27 +356,49 @@ const Separator = styled.span`
|
|
|
354
356
|
`;
|
|
355
357
|
|
|
356
358
|
const LootSearchContainer = styled.div`
|
|
357
|
-
padding:
|
|
359
|
+
padding: 8px;
|
|
360
|
+
background: rgba(0, 0, 0, 0.2);
|
|
361
|
+
border-radius: 4px;
|
|
362
|
+
margin: 8px 8px 4px;
|
|
363
|
+
box-sizing: border-box;
|
|
358
364
|
`;
|
|
359
365
|
|
|
360
366
|
const StyledSearchBar = styled(SearchBar)`
|
|
361
367
|
width: 100%;
|
|
368
|
+
box-sizing: border-box;
|
|
369
|
+
input {
|
|
370
|
+
background: rgba(0, 0, 0, 0.2) !important;
|
|
371
|
+
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
|
372
|
+
box-sizing: border-box;
|
|
373
|
+
&:focus {
|
|
374
|
+
border-color: ${uiColors.yellow} !important;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
362
377
|
`;
|
|
363
378
|
|
|
364
379
|
const LootGrid = styled.div`
|
|
365
380
|
display: grid;
|
|
366
|
-
grid-template-columns: repeat(auto-
|
|
367
|
-
gap:
|
|
368
|
-
padding:
|
|
381
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
382
|
+
gap: 4px;
|
|
383
|
+
padding: 4px 8px;
|
|
384
|
+
width: 100%;
|
|
385
|
+
max-width: 100%;
|
|
386
|
+
box-sizing: border-box;
|
|
387
|
+
|
|
388
|
+
@media (max-width: 768px) {
|
|
389
|
+
grid-template-columns: 1fr;
|
|
390
|
+
padding: 4px;
|
|
391
|
+
}
|
|
369
392
|
`;
|
|
370
393
|
|
|
371
394
|
const LootItem = styled.div`
|
|
372
395
|
display: flex;
|
|
373
396
|
align-items: center;
|
|
374
|
-
gap:
|
|
397
|
+
gap: 4px;
|
|
375
398
|
background: rgba(255, 255, 255, 0.05);
|
|
376
|
-
padding:
|
|
399
|
+
padding: 4px;
|
|
377
400
|
border-radius: 4px;
|
|
401
|
+
min-width: 0;
|
|
378
402
|
`;
|
|
379
403
|
|
|
380
404
|
const LootDetails = styled.div`
|
|
@@ -2,11 +2,13 @@ import {
|
|
|
2
2
|
IInformationCenterItem,
|
|
3
3
|
IInformationCenterNPC,
|
|
4
4
|
ItemType,
|
|
5
|
+
isMobileOrTablet,
|
|
5
6
|
} from '@rpg-engine/shared';
|
|
6
7
|
import React, { useState } from 'react';
|
|
7
8
|
import styled from 'styled-components';
|
|
8
9
|
import { IOptionsProps } from '../../../Dropdown';
|
|
9
10
|
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
|
|
11
|
+
import { Portal } from '../../../shared/Portal/Portal';
|
|
10
12
|
import { InformationCenterCell } from '../../InformationCenterCell';
|
|
11
13
|
import { InformationCenterItemDetails } from './InformationCenterItemDetails';
|
|
12
14
|
import { InformationCenterItemTooltip } from './InformationCenterItemTooltip';
|
|
@@ -47,6 +49,7 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
47
49
|
initialSearchQuery,
|
|
48
50
|
tabId,
|
|
49
51
|
}) => {
|
|
52
|
+
const isMobile = isMobileOrTablet();
|
|
50
53
|
const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
|
|
51
54
|
const [selectedItemCategory, setSelectedItemCategory] = useState<string>(
|
|
52
55
|
'all'
|
|
@@ -90,15 +93,17 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
90
93
|
e: React.MouseEvent,
|
|
91
94
|
item: IInformationCenterItem
|
|
92
95
|
) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
if (!isMobile) {
|
|
97
|
+
setTooltipPosition({
|
|
98
|
+
x: e.clientX + TOOLTIP_OFFSET,
|
|
99
|
+
y: e.clientY,
|
|
100
|
+
});
|
|
101
|
+
setHoveredItem(item);
|
|
102
|
+
}
|
|
98
103
|
};
|
|
99
104
|
|
|
100
105
|
const handleMouseMove = (e: React.MouseEvent) => {
|
|
101
|
-
if (hoveredItem) {
|
|
106
|
+
if (!isMobile && hoveredItem) {
|
|
102
107
|
setTooltipPosition({
|
|
103
108
|
x: e.clientX + TOOLTIP_OFFSET,
|
|
104
109
|
y: e.clientY,
|
|
@@ -107,19 +112,17 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
107
112
|
};
|
|
108
113
|
|
|
109
114
|
const handleMouseLeave = () => {
|
|
110
|
-
|
|
115
|
+
if (!isMobile) {
|
|
116
|
+
setHoveredItem(null);
|
|
117
|
+
}
|
|
111
118
|
};
|
|
112
119
|
|
|
113
120
|
const handleTouchStart = (
|
|
114
121
|
e: React.TouchEvent,
|
|
115
122
|
item: IInformationCenterItem
|
|
116
123
|
) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
x: touch.clientX + TOOLTIP_OFFSET,
|
|
120
|
-
y: touch.clientY,
|
|
121
|
-
});
|
|
122
|
-
setHoveredItem(item);
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
setSelectedItem(item);
|
|
123
126
|
};
|
|
124
127
|
|
|
125
128
|
const handleItemClick = (item: IInformationCenterItem) => {
|
|
@@ -170,7 +173,7 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
170
173
|
layout="grid"
|
|
171
174
|
itemHeight="180px"
|
|
172
175
|
/>
|
|
173
|
-
{hoveredItem && (
|
|
176
|
+
{!isMobile && hoveredItem && (
|
|
174
177
|
<TooltipWrapper
|
|
175
178
|
style={{ top: tooltipPosition.y, left: tooltipPosition.x }}
|
|
176
179
|
>
|
|
@@ -178,13 +181,15 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
178
181
|
</TooltipWrapper>
|
|
179
182
|
)}
|
|
180
183
|
{selectedItem && (
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
<Portal>
|
|
185
|
+
<InformationCenterItemDetails
|
|
186
|
+
item={selectedItem}
|
|
187
|
+
itemsAtlasJSON={itemsAtlasJSON}
|
|
188
|
+
itemsAtlasIMG={itemsAtlasIMG}
|
|
189
|
+
droppedBy={getDroppedByNPCs(selectedItem.key, bestiaryItems)}
|
|
190
|
+
onBack={() => setSelectedItem(null)}
|
|
191
|
+
/>
|
|
192
|
+
</Portal>
|
|
188
193
|
)}
|
|
189
194
|
</>
|
|
190
195
|
);
|
|
@@ -49,32 +49,45 @@ export const BaseInformationDetails: React.FC<IBaseInformationDetailsProps> = ({
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
const Container = styled.div`
|
|
52
|
-
position:
|
|
52
|
+
position: fixed;
|
|
53
53
|
inset: 0;
|
|
54
54
|
display: flex;
|
|
55
55
|
justify-content: center;
|
|
56
56
|
align-items: center;
|
|
57
|
-
z-index:
|
|
57
|
+
z-index: 9999;
|
|
58
58
|
`;
|
|
59
59
|
|
|
60
60
|
const Overlay = styled.div`
|
|
61
|
-
position:
|
|
61
|
+
position: fixed;
|
|
62
62
|
inset: 0;
|
|
63
63
|
background-color: rgba(0, 0, 0, 0.8);
|
|
64
64
|
`;
|
|
65
65
|
|
|
66
66
|
const Modal = styled.div`
|
|
67
|
-
position:
|
|
68
|
-
width: 90%;
|
|
69
|
-
height: 90%;
|
|
67
|
+
position: fixed;
|
|
70
68
|
background-color: rgba(0, 0, 0, 0.95);
|
|
71
69
|
border-radius: 4px;
|
|
72
|
-
padding:
|
|
73
|
-
overflow
|
|
70
|
+
padding: 12px;
|
|
71
|
+
overflow: hidden;
|
|
74
72
|
z-index: 1;
|
|
75
73
|
font-family: 'Press Start 2P', cursive;
|
|
76
74
|
border: 1px solid ${uiColors.darkGray};
|
|
77
75
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
76
|
+
width: 90%;
|
|
77
|
+
height: 90%;
|
|
78
|
+
top: 5%;
|
|
79
|
+
left: 5%;
|
|
80
|
+
max-width: 800px;
|
|
81
|
+
margin: 0 auto;
|
|
82
|
+
|
|
83
|
+
@media (max-width: 768px) {
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
top: 0;
|
|
87
|
+
left: 0;
|
|
88
|
+
border-radius: 0;
|
|
89
|
+
padding: 8px;
|
|
90
|
+
}
|
|
78
91
|
|
|
79
92
|
&::-webkit-scrollbar {
|
|
80
93
|
width: 2px;
|
|
@@ -126,9 +139,19 @@ const Header = styled.div`
|
|
|
126
139
|
const Content = styled.div`
|
|
127
140
|
display: flex;
|
|
128
141
|
flex-direction: column;
|
|
129
|
-
gap:
|
|
130
|
-
height: 100
|
|
131
|
-
overflow: auto;
|
|
142
|
+
gap: 12px;
|
|
143
|
+
height: calc(100% - 80px);
|
|
144
|
+
overflow-y: auto;
|
|
145
|
+
overflow-x: hidden;
|
|
146
|
+
padding-right: 6px;
|
|
147
|
+
margin-right: -6px;
|
|
148
|
+
|
|
149
|
+
@media (max-width: 768px) {
|
|
150
|
+
height: calc(100% - 64px);
|
|
151
|
+
gap: 8px;
|
|
152
|
+
padding-right: 4px;
|
|
153
|
+
margin-right: -4px;
|
|
154
|
+
}
|
|
132
155
|
`;
|
|
133
156
|
|
|
134
157
|
const Title = styled.h2`
|