@rpg-engine/long-bow 0.8.30 → 0.8.32
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/InformationCenter/sections/bestiary/BestiaryAdvancedFilters.d.ts +13 -0
- package/dist/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.d.ts +2 -2
- package/dist/components/InformationCenter/sections/items/ItemsAdvancedFilters.d.ts +11 -0
- package/dist/components/shared/AdvancedFilters/AdvancedFilters.d.ts +23 -0
- package/dist/components/shared/PaginatedContent/PaginatedContent.d.ts +1 -0
- package/dist/components/shared/SearchBar/SearchBar.d.ts +1 -0
- package/dist/components/shared/SearchHeader/SearchHeader.d.ts +1 -0
- package/dist/hooks/useTooltipPosition.d.ts +15 -0
- package/dist/long-bow.cjs.development.js +758 -509
- 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 +665 -416
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/components/InformationCenter/InformationCenter.tsx +5 -19
- package/src/components/InformationCenter/sections/bestiary/BestiaryAdvancedFilters.tsx +95 -0
- package/src/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.tsx +124 -84
- package/src/components/InformationCenter/sections/bestiary/InformationCenterNPCDetails.tsx +31 -7
- package/src/components/InformationCenter/sections/items/InformationCenterItemsSection.tsx +76 -78
- package/src/components/InformationCenter/sections/items/ItemsAdvancedFilters.tsx +80 -0
- package/src/components/InformationCenter/shared/BaseInformationDetails.tsx +34 -11
- package/src/components/Item/Cards/ItemInfo.tsx +1 -18
- package/src/components/Item/Inventory/ItemSlot.tsx +3 -15
- package/src/components/Item/Inventory/ItemSlotRenderer.tsx +2 -6
- package/src/components/shared/AdvancedFilters/AdvancedFilters.tsx +279 -0
- package/src/components/shared/Collapsible/Collapsible.tsx +1 -1
- package/src/components/shared/PaginatedContent/PaginatedContent.tsx +1 -0
- package/src/components/shared/SearchBar/SearchBar.tsx +15 -5
- package/src/components/shared/SearchHeader/SearchHeader.tsx +2 -0
- package/src/hooks/useTooltipPosition.ts +73 -0
- package/src/mocks/itemContainer.mocks.ts +0 -7
- package/dist/components/Item/Inventory/ItemSlotQuality.d.ts +0 -2
- package/src/components/Item/Inventory/ItemSlotQuality.ts +0 -18
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IInformationCenterItem,
|
|
3
3
|
IInformationCenterNPC,
|
|
4
|
-
|
|
4
|
+
isMobileOrTablet,
|
|
5
5
|
} from '@rpg-engine/shared';
|
|
6
|
-
import React, { useState } from 'react';
|
|
6
|
+
import React, { useMemo, useState } from 'react';
|
|
7
7
|
import styled from 'styled-components';
|
|
8
|
-
import {
|
|
8
|
+
import { useTooltipPosition } from '../../../../hooks/useTooltipPosition';
|
|
9
9
|
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
|
|
10
|
+
import { Portal } from '../../../shared/Portal/Portal';
|
|
10
11
|
import { InformationCenterCell } from '../../InformationCenterCell';
|
|
11
12
|
import { InformationCenterItemDetails } from './InformationCenterItemDetails';
|
|
12
13
|
import { InformationCenterItemTooltip } from './InformationCenterItemTooltip';
|
|
13
|
-
|
|
14
|
-
const TOOLTIP_OFFSET = 200;
|
|
14
|
+
import { ItemsAdvancedFilters } from './ItemsAdvancedFilters';
|
|
15
15
|
|
|
16
16
|
interface IItemsSectionProps {
|
|
17
17
|
items: IInformationCenterItem[];
|
|
@@ -47,33 +47,38 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
47
47
|
initialSearchQuery,
|
|
48
48
|
tabId,
|
|
49
49
|
}) => {
|
|
50
|
+
const isMobile = isMobileOrTablet();
|
|
50
51
|
const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
|
|
51
52
|
const [selectedItemCategory, setSelectedItemCategory] = useState<string>(
|
|
52
53
|
'all'
|
|
53
54
|
);
|
|
54
|
-
const [
|
|
55
|
-
|
|
56
|
-
);
|
|
57
|
-
const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
|
|
55
|
+
const [selectedTier, setSelectedTier] = useState<string>('all');
|
|
56
|
+
const [isAdvancedFiltersOpen, setIsAdvancedFiltersOpen] = useState(false);
|
|
58
57
|
const [
|
|
59
58
|
selectedItem,
|
|
60
59
|
setSelectedItem,
|
|
61
60
|
] = useState<IInformationCenterItem | null>(null);
|
|
62
61
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
]
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
const {
|
|
63
|
+
tooltipState,
|
|
64
|
+
handleMouseEnter,
|
|
65
|
+
handleMouseLeave,
|
|
66
|
+
TOOLTIP_WIDTH,
|
|
67
|
+
} = useTooltipPosition<IInformationCenterItem>();
|
|
68
|
+
|
|
69
|
+
const filteredItems = useMemo<IInformationCenterItem[]>(() => {
|
|
70
|
+
return items.filter(item => {
|
|
71
|
+
const matchesSearch = item.name
|
|
72
|
+
.toLowerCase()
|
|
73
|
+
.includes(searchQuery.toLowerCase());
|
|
74
|
+
const matchesCategory =
|
|
75
|
+
selectedItemCategory === 'all' || item.type === selectedItemCategory;
|
|
76
|
+
const matchesTier =
|
|
77
|
+
selectedTier === 'all' || String(item.tier) === selectedTier;
|
|
78
|
+
|
|
79
|
+
return matchesSearch && matchesCategory && matchesTier;
|
|
80
|
+
});
|
|
81
|
+
}, [items, searchQuery, selectedItemCategory, selectedTier]);
|
|
77
82
|
|
|
78
83
|
const getDroppedByNPCs = (
|
|
79
84
|
itemId: string,
|
|
@@ -86,45 +91,16 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
86
91
|
);
|
|
87
92
|
};
|
|
88
93
|
|
|
89
|
-
const handleMouseEnter = (
|
|
90
|
-
e: React.MouseEvent,
|
|
91
|
-
item: IInformationCenterItem
|
|
92
|
-
) => {
|
|
93
|
-
setTooltipPosition({
|
|
94
|
-
x: e.clientX + TOOLTIP_OFFSET,
|
|
95
|
-
y: e.clientY,
|
|
96
|
-
});
|
|
97
|
-
setHoveredItem(item);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const handleMouseMove = (e: React.MouseEvent) => {
|
|
101
|
-
if (hoveredItem) {
|
|
102
|
-
setTooltipPosition({
|
|
103
|
-
x: e.clientX + TOOLTIP_OFFSET,
|
|
104
|
-
y: e.clientY,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const handleMouseLeave = () => {
|
|
110
|
-
setHoveredItem(null);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
94
|
const handleTouchStart = (
|
|
114
95
|
e: React.TouchEvent,
|
|
115
96
|
item: IInformationCenterItem
|
|
116
97
|
) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
x: touch.clientX + TOOLTIP_OFFSET,
|
|
120
|
-
y: touch.clientY,
|
|
121
|
-
});
|
|
122
|
-
setHoveredItem(item);
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
setSelectedItem(item);
|
|
123
100
|
};
|
|
124
101
|
|
|
125
102
|
const handleItemClick = (item: IInformationCenterItem) => {
|
|
126
103
|
setSelectedItem(item);
|
|
127
|
-
setHoveredItem(null);
|
|
128
104
|
};
|
|
129
105
|
|
|
130
106
|
const handleSearchChange = (newQuery: string) => {
|
|
@@ -141,58 +117,80 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
141
117
|
spriteKey={item.texturePath}
|
|
142
118
|
atlasJSON={itemsAtlasJSON}
|
|
143
119
|
atlasIMG={itemsAtlasIMG}
|
|
144
|
-
onMouseEnter={e => handleMouseEnter(
|
|
145
|
-
onMouseMove={handleMouseMove}
|
|
120
|
+
onMouseEnter={e => handleMouseEnter(item, e)}
|
|
146
121
|
onMouseLeave={handleMouseLeave}
|
|
147
122
|
onTouchStart={e => handleTouchStart(e, item)}
|
|
148
123
|
onClick={() => handleItemClick(item)}
|
|
149
124
|
/>
|
|
150
125
|
);
|
|
151
126
|
|
|
127
|
+
const SearchBarRightElement = (
|
|
128
|
+
<SearchBarActions>
|
|
129
|
+
<ItemsAdvancedFilters
|
|
130
|
+
isOpen={isAdvancedFiltersOpen}
|
|
131
|
+
onToggle={() => setIsAdvancedFiltersOpen(!isAdvancedFiltersOpen)}
|
|
132
|
+
onTierChange={setSelectedTier}
|
|
133
|
+
onTypeChange={setSelectedItemCategory}
|
|
134
|
+
selectedTier={selectedTier}
|
|
135
|
+
selectedType={selectedItemCategory}
|
|
136
|
+
/>
|
|
137
|
+
</SearchBarActions>
|
|
138
|
+
);
|
|
139
|
+
|
|
152
140
|
return (
|
|
153
141
|
<>
|
|
154
142
|
<PaginatedContent<IInformationCenterItem>
|
|
155
143
|
items={filteredItems}
|
|
156
144
|
renderItem={renderItem}
|
|
157
145
|
emptyMessage="No items found"
|
|
158
|
-
filterOptions={{
|
|
159
|
-
options: itemCategoryOptions,
|
|
160
|
-
selectedOption: selectedItemCategory,
|
|
161
|
-
onOptionChange: setSelectedItemCategory,
|
|
162
|
-
}}
|
|
163
146
|
searchOptions={{
|
|
164
147
|
value: searchQuery,
|
|
165
148
|
onChange: handleSearchChange,
|
|
166
149
|
placeholder: 'Search items...',
|
|
150
|
+
rightElement: SearchBarRightElement,
|
|
167
151
|
}}
|
|
168
|
-
dependencies={[selectedItemCategory]}
|
|
152
|
+
dependencies={[selectedItemCategory, selectedTier]}
|
|
169
153
|
tabId={tabId}
|
|
170
154
|
layout="grid"
|
|
171
155
|
itemHeight="180px"
|
|
172
156
|
/>
|
|
173
|
-
{
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
157
|
+
{!isMobile && tooltipState && tooltipState.item && (
|
|
158
|
+
<Portal>
|
|
159
|
+
<TooltipWrapper
|
|
160
|
+
width={TOOLTIP_WIDTH}
|
|
161
|
+
style={{
|
|
162
|
+
position: 'fixed',
|
|
163
|
+
left: `${tooltipState.position.x}px`,
|
|
164
|
+
top: `${tooltipState.position.y}px`,
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
<InformationCenterItemTooltip item={tooltipState.item} />
|
|
168
|
+
</TooltipWrapper>
|
|
169
|
+
</Portal>
|
|
179
170
|
)}
|
|
180
171
|
{selectedItem && (
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
172
|
+
<Portal>
|
|
173
|
+
<InformationCenterItemDetails
|
|
174
|
+
item={selectedItem}
|
|
175
|
+
itemsAtlasJSON={itemsAtlasJSON}
|
|
176
|
+
itemsAtlasIMG={itemsAtlasIMG}
|
|
177
|
+
droppedBy={getDroppedByNPCs(selectedItem.key, bestiaryItems)}
|
|
178
|
+
onBack={() => setSelectedItem(null)}
|
|
179
|
+
/>
|
|
180
|
+
</Portal>
|
|
188
181
|
)}
|
|
189
182
|
</>
|
|
190
183
|
);
|
|
191
184
|
};
|
|
192
185
|
|
|
193
|
-
const TooltipWrapper = styled.div
|
|
194
|
-
position: fixed;
|
|
186
|
+
const TooltipWrapper = styled.div<{ width: number }>`
|
|
195
187
|
z-index: 1000;
|
|
196
188
|
pointer-events: none;
|
|
197
|
-
|
|
189
|
+
width: ${props => `${props.width}px`};
|
|
190
|
+
`;
|
|
191
|
+
|
|
192
|
+
const SearchBarActions = styled.div`
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 0.5rem;
|
|
198
196
|
`;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ItemType } from '@rpg-engine/shared';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import {
|
|
4
|
+
AdvancedFilters,
|
|
5
|
+
IFilterOption,
|
|
6
|
+
IFilterSection,
|
|
7
|
+
} from '../../../shared/AdvancedFilters/AdvancedFilters';
|
|
8
|
+
import { formatItemType } from './InformationCenterItemsSection';
|
|
9
|
+
|
|
10
|
+
interface IItemsAdvancedFiltersProps {
|
|
11
|
+
isOpen: boolean;
|
|
12
|
+
onToggle: () => void;
|
|
13
|
+
onTierChange: (value: string) => void;
|
|
14
|
+
onTypeChange: (value: string) => void;
|
|
15
|
+
selectedTier: string;
|
|
16
|
+
selectedType: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const ItemsAdvancedFilters = ({
|
|
20
|
+
isOpen,
|
|
21
|
+
onToggle,
|
|
22
|
+
onTierChange,
|
|
23
|
+
onTypeChange,
|
|
24
|
+
selectedTier,
|
|
25
|
+
selectedType,
|
|
26
|
+
}: IItemsAdvancedFiltersProps): JSX.Element => {
|
|
27
|
+
const tierOptions: IFilterOption[] = [
|
|
28
|
+
{ id: 0, value: 'all', option: 'All Tiers' },
|
|
29
|
+
...Array.from({ length: 5 }, (_, i) => ({
|
|
30
|
+
id: i + 1,
|
|
31
|
+
value: String(i + 1),
|
|
32
|
+
option: `Tier ${i + 1}`,
|
|
33
|
+
})),
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const typeOptions: IFilterOption[] = [
|
|
37
|
+
{ id: 0, value: 'all', option: 'All Types' },
|
|
38
|
+
...Object.entries(ItemType).map(([, value], index) => ({
|
|
39
|
+
id: index + 1,
|
|
40
|
+
value: value as string,
|
|
41
|
+
option: formatItemType(value as string),
|
|
42
|
+
})),
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const hasActiveFilters = selectedTier !== 'all' || selectedType !== 'all';
|
|
46
|
+
|
|
47
|
+
const handleClearFilters = () => {
|
|
48
|
+
onTierChange('all');
|
|
49
|
+
onTypeChange('all');
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const sections: IFilterSection[] = [
|
|
53
|
+
{
|
|
54
|
+
type: 'dropdown',
|
|
55
|
+
label: 'Tier',
|
|
56
|
+
key: 'tier',
|
|
57
|
+
options: tierOptions,
|
|
58
|
+
value: selectedTier,
|
|
59
|
+
onChange: onTierChange,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: 'dropdown',
|
|
63
|
+
label: 'Item Type',
|
|
64
|
+
key: 'type',
|
|
65
|
+
options: typeOptions,
|
|
66
|
+
value: selectedType,
|
|
67
|
+
onChange: onTypeChange,
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<AdvancedFilters
|
|
73
|
+
isOpen={isOpen}
|
|
74
|
+
onToggle={onToggle}
|
|
75
|
+
sections={sections}
|
|
76
|
+
onClearAll={handleClearFilters}
|
|
77
|
+
hasActiveFilters={hasActiveFilters}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
@@ -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`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IItem
|
|
1
|
+
import { IItem } from '@rpg-engine/shared';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { uiColors } from '../../../constants/uiColors';
|
|
@@ -6,7 +6,6 @@ import { uiFonts } from '../../../constants/uiFonts';
|
|
|
6
6
|
import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
|
|
7
7
|
import { ErrorBoundary } from '../Inventory/ErrorBoundary';
|
|
8
8
|
import { EquipmentSlotSpriteByType } from '../Inventory/ItemSlot';
|
|
9
|
-
import { qualityColorHex } from '../Inventory/ItemSlotQuality';
|
|
10
9
|
import { rarityColor } from '../Inventory/ItemSlotRarity';
|
|
11
10
|
|
|
12
11
|
interface IItemInfoProps {
|
|
@@ -192,24 +191,8 @@ const Container = styled.div<{ item: IItem }>`
|
|
|
192
191
|
padding: 0.5rem;
|
|
193
192
|
font-size: ${uiFonts.size.small};
|
|
194
193
|
border: 3px solid ${({ item }) => rarityColor(item) ?? uiColors.lightGray};
|
|
195
|
-
box-shadow: ${({ item }) => `0 0 5px 2px ${rarityColor(item)}`};
|
|
196
194
|
height: max-content;
|
|
197
195
|
width: 18rem;
|
|
198
|
-
position: relative;
|
|
199
|
-
|
|
200
|
-
${({ item }) =>
|
|
201
|
-
item?.quality && item.quality !== ItemQualityLevel.Normal &&
|
|
202
|
-
`
|
|
203
|
-
&::before {
|
|
204
|
-
content: '★';
|
|
205
|
-
position: absolute;
|
|
206
|
-
top: 0.2rem;
|
|
207
|
-
left: 0.5rem;
|
|
208
|
-
font-size: 1.2rem;
|
|
209
|
-
color: ${qualityColorHex(item)};
|
|
210
|
-
text-shadow: 0 0 3px black;
|
|
211
|
-
}
|
|
212
|
-
`}
|
|
213
196
|
|
|
214
197
|
@media (max-width: 640px) {
|
|
215
198
|
width: 80vw;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ItemContainerType,
|
|
7
7
|
ItemSlotType,
|
|
8
8
|
ItemSubType,
|
|
9
|
-
ItemType
|
|
9
|
+
ItemType,
|
|
10
10
|
} from '@rpg-engine/shared';
|
|
11
11
|
|
|
12
12
|
import { observer } from 'mobx-react-lite';
|
|
@@ -15,11 +15,10 @@ import Draggable, { DraggableEventHandler } from 'react-draggable';
|
|
|
15
15
|
import styled from 'styled-components';
|
|
16
16
|
import useTouchTarget from '../../../hooks/useTouchTarget';
|
|
17
17
|
import { IPosition } from '../../../types/eventTypes';
|
|
18
|
-
import { useItemSlotDetails } from './context/ItemSlotDetailsContext';
|
|
19
|
-
import { useItemSlotDragging } from './context/ItemSlotDraggingContext';
|
|
20
|
-
import { qualityColorHex } from './ItemSlotQuality';
|
|
21
18
|
import { rarityColor } from './ItemSlotRarity';
|
|
22
19
|
import { ItemSlotRenderer } from './ItemSlotRenderer';
|
|
20
|
+
import { useItemSlotDetails } from './context/ItemSlotDetailsContext';
|
|
21
|
+
import { useItemSlotDragging } from './context/ItemSlotDraggingContext';
|
|
23
22
|
|
|
24
23
|
export const EquipmentSlotSpriteByType: any = {
|
|
25
24
|
Neck: 'accessories/corruption-necklace.png',
|
|
@@ -540,17 +539,6 @@ const Container = styled.div<ContainerTypes>`
|
|
|
540
539
|
${({ item }) => `0 0 4px 3px ${rarityColor(item)}`};
|
|
541
540
|
}
|
|
542
541
|
|
|
543
|
-
.quality-star {
|
|
544
|
-
position: absolute;
|
|
545
|
-
top: 0.5rem;
|
|
546
|
-
left: 0.5rem;
|
|
547
|
-
font-size: 1.2rem;
|
|
548
|
-
z-index: 2;
|
|
549
|
-
text-shadow: 0 0 3px black;
|
|
550
|
-
pointer-events: none;
|
|
551
|
-
color: ${({ item }) => qualityColorHex(item)};
|
|
552
|
-
}
|
|
553
|
-
|
|
554
542
|
&::before {
|
|
555
543
|
content: '';
|
|
556
544
|
position: absolute;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
getItemTextureKeyPath,
|
|
3
2
|
IItem,
|
|
4
3
|
ItemContainerType,
|
|
5
|
-
ItemQualityLevel,
|
|
6
4
|
ItemSlotType,
|
|
5
|
+
getItemTextureKeyPath,
|
|
7
6
|
} from '@rpg-engine/shared';
|
|
8
7
|
import React from 'react';
|
|
9
8
|
import { v4 as uuidv4 } from 'uuid';
|
|
@@ -47,9 +46,6 @@ export const ItemSlotRenderer: React.FC<IProps> = ({
|
|
|
47
46
|
|
|
48
47
|
return (
|
|
49
48
|
<ErrorBoundary key={item._id}>
|
|
50
|
-
{item.quality && item.quality !== ItemQualityLevel.Normal && (
|
|
51
|
-
<div className="quality-star">★</div>
|
|
52
|
-
)}
|
|
53
49
|
<SpriteFromAtlas
|
|
54
50
|
atlasIMG={atlasIMG}
|
|
55
51
|
atlasJSON={atlasJSON}
|
|
@@ -105,5 +101,5 @@ export const ItemSlotRenderer: React.FC<IProps> = ({
|
|
|
105
101
|
}
|
|
106
102
|
};
|
|
107
103
|
|
|
108
|
-
return onRenderSlot(item)
|
|
104
|
+
return <>{onRenderSlot(item)}</>;
|
|
109
105
|
};
|