@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.32",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@capacitor/core": "^6.1.0",
|
|
86
86
|
"@rollup/plugin-image": "^2.1.1",
|
|
87
|
-
"@rpg-engine/shared": "^0.
|
|
87
|
+
"@rpg-engine/shared": "^0.10.0",
|
|
88
88
|
"dayjs": "^1.11.2",
|
|
89
89
|
"font-awesome": "^4.7.0",
|
|
90
90
|
"fs-extra": "^10.1.0",
|
|
@@ -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
|
);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { EntityAttackType, NPCSubtype } from '@rpg-engine/shared';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import {
|
|
4
|
+
AdvancedFilters,
|
|
5
|
+
IFilterSection,
|
|
6
|
+
} from '../../../shared/AdvancedFilters/AdvancedFilters';
|
|
7
|
+
import { formatItemType } from '../items/InformationCenterItemsSection';
|
|
8
|
+
|
|
9
|
+
interface IBestiaryAdvancedFiltersProps {
|
|
10
|
+
isOpen: boolean;
|
|
11
|
+
onToggle: () => void;
|
|
12
|
+
onLevelRangeChange: (range: [number | undefined, number | undefined]) => void;
|
|
13
|
+
onSubtypeChange: (value: string) => void;
|
|
14
|
+
onAttackTypeChange: (value: string) => void;
|
|
15
|
+
levelRange: [number | undefined, number | undefined];
|
|
16
|
+
selectedSubtype: string;
|
|
17
|
+
selectedAttackType: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const BestiaryAdvancedFilters = ({
|
|
21
|
+
isOpen,
|
|
22
|
+
onToggle,
|
|
23
|
+
onLevelRangeChange,
|
|
24
|
+
onSubtypeChange,
|
|
25
|
+
onAttackTypeChange,
|
|
26
|
+
levelRange,
|
|
27
|
+
selectedSubtype,
|
|
28
|
+
selectedAttackType,
|
|
29
|
+
}: IBestiaryAdvancedFiltersProps): JSX.Element => {
|
|
30
|
+
const subtypeOptions = [
|
|
31
|
+
{ id: 0, value: 'all', option: 'All Types' },
|
|
32
|
+
...Object.entries(NPCSubtype).map(([, value], index) => ({
|
|
33
|
+
id: index + 1,
|
|
34
|
+
value,
|
|
35
|
+
option: formatItemType(value),
|
|
36
|
+
})),
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const attackTypeOptions = [
|
|
40
|
+
{ id: 0, value: 'all', option: 'All Attack Types' },
|
|
41
|
+
...Object.entries(EntityAttackType).map(([, value], index) => ({
|
|
42
|
+
id: index + 1,
|
|
43
|
+
value,
|
|
44
|
+
option: formatItemType(value),
|
|
45
|
+
})),
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const hasActiveFilters =
|
|
49
|
+
levelRange[0] !== undefined ||
|
|
50
|
+
levelRange[1] !== undefined ||
|
|
51
|
+
selectedSubtype !== 'all' ||
|
|
52
|
+
selectedAttackType !== 'all';
|
|
53
|
+
|
|
54
|
+
const handleClearFilters = () => {
|
|
55
|
+
onLevelRangeChange([undefined, undefined]);
|
|
56
|
+
onSubtypeChange('all');
|
|
57
|
+
onAttackTypeChange('all');
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const sections: IFilterSection[] = [
|
|
61
|
+
{
|
|
62
|
+
type: 'range',
|
|
63
|
+
label: 'Level Range',
|
|
64
|
+
key: 'level',
|
|
65
|
+
value: levelRange,
|
|
66
|
+
onChange: onLevelRangeChange,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: 'dropdown',
|
|
70
|
+
label: 'Monster Type',
|
|
71
|
+
key: 'subtype',
|
|
72
|
+
options: subtypeOptions,
|
|
73
|
+
value: selectedSubtype,
|
|
74
|
+
onChange: onSubtypeChange,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'dropdown',
|
|
78
|
+
label: 'Attack Type',
|
|
79
|
+
key: 'attackType',
|
|
80
|
+
options: attackTypeOptions,
|
|
81
|
+
value: selectedAttackType,
|
|
82
|
+
onChange: onAttackTypeChange,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<AdvancedFilters
|
|
88
|
+
isOpen={isOpen}
|
|
89
|
+
onToggle={onToggle}
|
|
90
|
+
sections={sections}
|
|
91
|
+
onClearAll={handleClearFilters}
|
|
92
|
+
hasActiveFilters={hasActiveFilters}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
};
|
package/src/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.tsx
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
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';
|
|
8
|
+
import { useTooltipPosition } from '../../../../hooks/useTooltipPosition';
|
|
4
9
|
import { IOptionsProps } from '../../../Dropdown';
|
|
5
10
|
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
|
|
6
11
|
import { Portal } from '../../../shared/Portal/Portal';
|
|
7
12
|
import { InformationCenterCell } from '../../InformationCenterCell';
|
|
8
13
|
import { formatItemType } from '../items/InformationCenterItemsSection';
|
|
14
|
+
import { BestiaryAdvancedFilters } from './BestiaryAdvancedFilters';
|
|
9
15
|
import { InformationCenterNPCDetails } from './InformationCenterNPCDetails';
|
|
10
16
|
import { InformationCenterNPCTooltip } from './InformationCenterNPCTooltip';
|
|
17
|
+
|
|
11
18
|
interface IBestiarySectionProps {
|
|
12
19
|
bestiaryItems: IInformationCenterNPC[];
|
|
13
20
|
itemsAtlasJSON: Record<string, any>;
|
|
@@ -20,7 +27,7 @@ interface IBestiarySectionProps {
|
|
|
20
27
|
tabId: string;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
export const InformationCenterBestiarySection
|
|
30
|
+
export const InformationCenterBestiarySection = ({
|
|
24
31
|
bestiaryItems,
|
|
25
32
|
itemsAtlasJSON,
|
|
26
33
|
itemsAtlasIMG,
|
|
@@ -30,83 +37,59 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
30
37
|
entitiesAtlasIMG,
|
|
31
38
|
initialSearchQuery,
|
|
32
39
|
tabId,
|
|
33
|
-
}) => {
|
|
34
|
-
const
|
|
35
|
-
const [
|
|
36
|
-
npc: IInformationCenterNPC;
|
|
37
|
-
position: { x: number; y: number };
|
|
38
|
-
} | null>(null);
|
|
40
|
+
}: IBestiarySectionProps): JSX.Element => {
|
|
41
|
+
const isMobile = isMobileOrTablet();
|
|
42
|
+
const [searchQuery, setSearchQuery] = useState<string>(initialSearchQuery);
|
|
39
43
|
const [
|
|
40
44
|
selectedMonster,
|
|
41
45
|
setSelectedMonster,
|
|
42
46
|
] = useState<IInformationCenterNPC | null>(null);
|
|
43
|
-
const [
|
|
47
|
+
const [selectedBestiaryCategory, setSelectedBestiaryCategory] = useState<
|
|
48
|
+
string
|
|
49
|
+
>('all');
|
|
44
50
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
npc: monster,
|
|
52
|
-
position: { x: event.clientX, y: event.clientY },
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
};
|
|
51
|
+
const {
|
|
52
|
+
tooltipState,
|
|
53
|
+
handleMouseEnter,
|
|
54
|
+
handleMouseLeave,
|
|
55
|
+
TOOLTIP_WIDTH,
|
|
56
|
+
} = useTooltipPosition<IInformationCenterNPC>();
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
...tooltipData,
|
|
67
|
-
position: { x: event.clientX, y: event.clientY },
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
};
|
|
58
|
+
// Advanced filters state
|
|
59
|
+
const [isAdvancedFiltersOpen, setIsAdvancedFiltersOpen] = useState<boolean>(
|
|
60
|
+
false
|
|
61
|
+
);
|
|
62
|
+
const [levelRange, setLevelRange] = useState<
|
|
63
|
+
[number | undefined, number | undefined]
|
|
64
|
+
>([undefined, undefined]);
|
|
65
|
+
const [selectedSubtype, setSelectedSubtype] = useState<string>('all');
|
|
66
|
+
const [selectedAttackType, setSelectedAttackType] = useState<string>('all');
|
|
71
67
|
|
|
72
68
|
const handleTouchStart = (
|
|
73
69
|
monster: IInformationCenterNPC,
|
|
74
70
|
event: React.TouchEvent
|
|
75
|
-
) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const touch = event.touches[0];
|
|
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
|
-
}
|
|
71
|
+
): void => {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
setSelectedMonster(monster);
|
|
88
74
|
};
|
|
89
75
|
|
|
90
|
-
const handleMonsterClick = (monster: IInformationCenterNPC) => {
|
|
76
|
+
const handleMonsterClick = (monster: IInformationCenterNPC): void => {
|
|
91
77
|
setSelectedMonster(monster);
|
|
92
|
-
setTooltipData(null);
|
|
93
78
|
};
|
|
94
79
|
|
|
95
|
-
const [selectedBestiaryCategory, setSelectedBestiaryCategory] = useState<
|
|
96
|
-
string
|
|
97
|
-
>('all');
|
|
98
|
-
|
|
99
80
|
const bestiaryCategoryOptions: IOptionsProps[] = [
|
|
100
81
|
{ id: 0, value: 'all', option: 'All Monsters' },
|
|
101
82
|
{ id: 1, value: 'bosses', option: 'Bosses' },
|
|
102
|
-
...Object.entries(NPCAlignment)
|
|
103
|
-
|
|
104
|
-
value,
|
|
105
|
-
|
|
106
|
-
|
|
83
|
+
...Object.entries(NPCAlignment)
|
|
84
|
+
.filter(([, value]) => value !== NPCAlignment.Friendly)
|
|
85
|
+
.map(([, value], index) => ({
|
|
86
|
+
id: index + 2,
|
|
87
|
+
value,
|
|
88
|
+
option: formatItemType(value),
|
|
89
|
+
})),
|
|
107
90
|
];
|
|
108
91
|
|
|
109
|
-
const renderItem = (item: IInformationCenterNPC) => (
|
|
92
|
+
const renderItem = (item: IInformationCenterNPC): JSX.Element => (
|
|
110
93
|
<InformationCenterCell
|
|
111
94
|
key={item.id}
|
|
112
95
|
name={item.name}
|
|
@@ -116,19 +99,19 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
116
99
|
onClick={() => handleMonsterClick(item)}
|
|
117
100
|
onMouseEnter={e => handleMouseEnter(item, e)}
|
|
118
101
|
onMouseLeave={handleMouseLeave}
|
|
119
|
-
onMouseMove={handleMouseMove}
|
|
120
102
|
onTouchStart={e => handleTouchStart(item, e)}
|
|
121
103
|
/>
|
|
122
104
|
);
|
|
123
105
|
|
|
124
|
-
const filteredItems = useMemo(() => {
|
|
106
|
+
const filteredItems = useMemo<IInformationCenterNPC[]>(() => {
|
|
125
107
|
return bestiaryItems.filter(item => {
|
|
108
|
+
// Basic search filter
|
|
126
109
|
const matchesSearch = item.name
|
|
127
110
|
.toLowerCase()
|
|
128
111
|
.includes(searchQuery.toLowerCase());
|
|
129
112
|
|
|
113
|
+
// Category filter
|
|
130
114
|
let matchesCategory = true;
|
|
131
|
-
|
|
132
115
|
if (selectedBestiaryCategory === 'bosses') {
|
|
133
116
|
matchesCategory = item.isBoss === true;
|
|
134
117
|
} else if (selectedBestiaryCategory === NPCAlignment.Hostile) {
|
|
@@ -138,17 +121,60 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
138
121
|
matchesCategory = item.alignment === selectedBestiaryCategory;
|
|
139
122
|
}
|
|
140
123
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
124
|
+
// Advanced filters
|
|
125
|
+
const matchesLevel =
|
|
126
|
+
(!levelRange[0] || item.skills.level >= levelRange[0]) &&
|
|
127
|
+
(!levelRange[1] || item.skills.level <= levelRange[1]);
|
|
128
|
+
|
|
129
|
+
const matchesSubtype =
|
|
130
|
+
selectedSubtype === 'all' || item.subType === selectedSubtype;
|
|
131
|
+
|
|
132
|
+
const matchesAttackType =
|
|
133
|
+
selectedAttackType === 'all' || item.attackType === selectedAttackType;
|
|
134
|
+
|
|
135
|
+
// Filter out friendly NPCs
|
|
136
|
+
const isNotFriendly = item.alignment !== NPCAlignment.Friendly;
|
|
144
137
|
|
|
145
|
-
|
|
138
|
+
return (
|
|
139
|
+
matchesSearch &&
|
|
140
|
+
matchesCategory &&
|
|
141
|
+
matchesLevel &&
|
|
142
|
+
matchesSubtype &&
|
|
143
|
+
matchesAttackType &&
|
|
144
|
+
isNotFriendly
|
|
145
|
+
);
|
|
146
|
+
});
|
|
147
|
+
}, [
|
|
148
|
+
bestiaryItems,
|
|
149
|
+
searchQuery,
|
|
150
|
+
selectedBestiaryCategory,
|
|
151
|
+
levelRange,
|
|
152
|
+
selectedSubtype,
|
|
153
|
+
selectedAttackType,
|
|
154
|
+
]);
|
|
155
|
+
|
|
156
|
+
const handleSearchChange = (newQuery: string): void => {
|
|
146
157
|
setSearchQuery(newQuery);
|
|
147
158
|
if (newQuery && selectedBestiaryCategory !== 'all') {
|
|
148
159
|
setSelectedBestiaryCategory('all');
|
|
149
160
|
}
|
|
150
161
|
};
|
|
151
162
|
|
|
163
|
+
const SearchBarRightElement = (
|
|
164
|
+
<SearchBarActions>
|
|
165
|
+
<BestiaryAdvancedFilters
|
|
166
|
+
isOpen={isAdvancedFiltersOpen}
|
|
167
|
+
onToggle={() => setIsAdvancedFiltersOpen(!isAdvancedFiltersOpen)}
|
|
168
|
+
onLevelRangeChange={setLevelRange}
|
|
169
|
+
onSubtypeChange={setSelectedSubtype}
|
|
170
|
+
onAttackTypeChange={setSelectedAttackType}
|
|
171
|
+
levelRange={levelRange}
|
|
172
|
+
selectedSubtype={selectedSubtype}
|
|
173
|
+
selectedAttackType={selectedAttackType}
|
|
174
|
+
/>
|
|
175
|
+
</SearchBarActions>
|
|
176
|
+
);
|
|
177
|
+
|
|
152
178
|
return (
|
|
153
179
|
<>
|
|
154
180
|
<PaginatedContent<IInformationCenterNPC>
|
|
@@ -166,21 +192,28 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
166
192
|
value: searchQuery,
|
|
167
193
|
onChange: handleSearchChange,
|
|
168
194
|
placeholder: 'Search monsters...',
|
|
195
|
+
rightElement: SearchBarRightElement,
|
|
169
196
|
}}
|
|
170
|
-
dependencies={[
|
|
197
|
+
dependencies={[
|
|
198
|
+
selectedBestiaryCategory,
|
|
199
|
+
levelRange,
|
|
200
|
+
selectedSubtype,
|
|
201
|
+
selectedAttackType,
|
|
202
|
+
]}
|
|
171
203
|
itemHeight="180px"
|
|
172
204
|
/>
|
|
173
|
-
{
|
|
205
|
+
{!isMobile && tooltipState && tooltipState.item && (
|
|
174
206
|
<Portal>
|
|
175
207
|
<TooltipWrapper
|
|
208
|
+
width={TOOLTIP_WIDTH}
|
|
176
209
|
style={{
|
|
177
210
|
position: 'fixed',
|
|
178
|
-
left:
|
|
179
|
-
top:
|
|
211
|
+
left: `${tooltipState.position.x}px`,
|
|
212
|
+
top: `${tooltipState.position.y}px`,
|
|
180
213
|
}}
|
|
181
214
|
>
|
|
182
215
|
<InformationCenterNPCTooltip
|
|
183
|
-
npc={
|
|
216
|
+
npc={tooltipState.item}
|
|
184
217
|
itemsAtlasJSON={itemsAtlasJSON}
|
|
185
218
|
itemsAtlasIMG={itemsAtlasIMG}
|
|
186
219
|
/>
|
|
@@ -188,24 +221,31 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
|
|
|
188
221
|
</Portal>
|
|
189
222
|
)}
|
|
190
223
|
{selectedMonster && (
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
224
|
+
<Portal>
|
|
225
|
+
<InformationCenterNPCDetails
|
|
226
|
+
npc={selectedMonster}
|
|
227
|
+
itemsAtlasJSON={itemsAtlasJSON}
|
|
228
|
+
itemsAtlasIMG={itemsAtlasIMG}
|
|
229
|
+
iconAtlasIMG={iconsAtlasIMG}
|
|
230
|
+
iconAtlasJSON={iconsAtlasJSON}
|
|
231
|
+
entitiesAtlasJSON={entitiesAtlasJSON}
|
|
232
|
+
entitiesAtlasIMG={entitiesAtlasIMG}
|
|
233
|
+
onBack={() => setSelectedMonster(null)}
|
|
234
|
+
/>
|
|
235
|
+
</Portal>
|
|
201
236
|
)}
|
|
202
237
|
</>
|
|
203
238
|
);
|
|
204
239
|
};
|
|
205
240
|
|
|
206
|
-
const TooltipWrapper = styled.div
|
|
207
|
-
position: fixed;
|
|
241
|
+
const TooltipWrapper = styled.div<{ width: number }>`
|
|
208
242
|
z-index: 1000;
|
|
209
243
|
pointer-events: none;
|
|
210
|
-
width:
|
|
244
|
+
width: ${props => `${props.width}px`};
|
|
245
|
+
`;
|
|
246
|
+
|
|
247
|
+
const SearchBarActions = styled.div`
|
|
248
|
+
display: flex;
|
|
249
|
+
align-items: center;
|
|
250
|
+
gap: 0.5rem;
|
|
211
251
|
`;
|
|
@@ -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`
|