@rpg-engine/long-bow 0.8.21 → 0.8.23
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/InformationCenter.d.ts +16 -13
- package/dist/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.d.ts +1 -1
- package/dist/components/InformationCenter/sections/bestiary/InformationCenterNPCDetails.d.ts +2 -1
- package/dist/components/InformationCenter/sections/bestiary/InformationCenterNPCTooltip.d.ts +1 -1
- package/dist/components/InformationCenter/sections/faq/InformationCenterFaqSection.d.ts +1 -1
- package/dist/components/InformationCenter/sections/items/InformationCenterItemDetails.d.ts +1 -1
- package/dist/components/InformationCenter/sections/items/InformationCenterItemTooltip.d.ts +1 -1
- package/dist/components/InformationCenter/sections/items/InformationCenterItemsSection.d.ts +2 -1
- package/dist/components/InformationCenter/sections/tutorials/InformationCenterTutorialsSection.d.ts +1 -1
- package/dist/long-bow.cjs.development.js +795 -688
- 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 +796 -689
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/mocks/informationCenter.mocks.d.ts +1 -2
- package/package.json +2 -2
- package/src/components/CraftBook/CraftBook.tsx +1 -1
- package/src/components/Dropdown.tsx +25 -3
- package/src/components/InformationCenter/InformationCenter.tsx +125 -124
- package/src/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.tsx +52 -7
- package/src/components/InformationCenter/sections/bestiary/InformationCenterNPCDetails.tsx +201 -207
- package/src/components/InformationCenter/sections/bestiary/InformationCenterNPCTooltip.tsx +7 -6
- package/src/components/InformationCenter/sections/faq/InformationCenterFaqSection.tsx +1 -1
- package/src/components/InformationCenter/sections/items/InformationCenterItemDetails.tsx +8 -6
- package/src/components/InformationCenter/sections/items/InformationCenterItemTooltip.tsx +1 -1
- package/src/components/InformationCenter/sections/items/InformationCenterItemsSection.tsx +36 -10
- package/src/components/InformationCenter/sections/tutorials/InformationCenterTutorialsSection.tsx +146 -36
- package/src/components/InformationCenter/shared/BaseInformationDetails.tsx +2 -0
- package/src/mocks/informationCenter.mocks.ts +159 -48
- package/src/stories/UI/info/InformationCenter.stories.tsx +1 -1
- package/dist/components/InformationCenter/InformationCenterTypes.d.ts +0 -96
- package/src/components/InformationCenter/InformationCenterTypes.ts +0 -105
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IInformationCenterNPC,
|
|
3
|
+
isMobileOrTablet,
|
|
4
|
+
MovementSpeed,
|
|
5
|
+
RangeTypes,
|
|
6
|
+
} from '@rpg-engine/shared';
|
|
2
7
|
import React, { useState } from 'react';
|
|
3
8
|
import styled from 'styled-components';
|
|
4
9
|
import { uiColors } from '../../../../constants/uiColors';
|
|
@@ -6,10 +11,7 @@ import { Collapsible } from '../../../shared/Collapsible/Collapsible';
|
|
|
6
11
|
import { Pagination } from '../../../shared/Pagination/Pagination';
|
|
7
12
|
import { SearchBar } from '../../../shared/SearchBar/SearchBar';
|
|
8
13
|
import { SpriteFromAtlas } from '../../../shared/SpriteFromAtlas';
|
|
9
|
-
|
|
10
|
-
IInformationCenterNPC,
|
|
11
|
-
MovementSpeed,
|
|
12
|
-
} from '../../InformationCenterTypes';
|
|
14
|
+
|
|
13
15
|
import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
|
|
14
16
|
|
|
15
17
|
interface INPCDetailsProps {
|
|
@@ -25,7 +27,7 @@ interface INPCDetailsProps {
|
|
|
25
27
|
|
|
26
28
|
const ITEMS_PER_PAGE = 5;
|
|
27
29
|
|
|
28
|
-
const formatItemName = (itemPath: string): string => {
|
|
30
|
+
export const formatItemName = (itemPath: string): string => {
|
|
29
31
|
const cleanText =
|
|
30
32
|
itemPath
|
|
31
33
|
.split('/')
|
|
@@ -40,207 +42,199 @@ const formatItemName = (itemPath: string): string => {
|
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
</SpellItem>
|
|
237
|
-
))}
|
|
238
|
-
</SpellsList>
|
|
239
|
-
</StyledCollapsible>
|
|
240
|
-
)}
|
|
241
|
-
</BaseInformationDetails>
|
|
242
|
-
);
|
|
243
|
-
};
|
|
45
|
+
npc,
|
|
46
|
+
itemsAtlasJSON,
|
|
47
|
+
itemsAtlasIMG,
|
|
48
|
+
entitiesAtlasJSON,
|
|
49
|
+
entitiesAtlasIMG,
|
|
50
|
+
iconAtlasIMG,
|
|
51
|
+
iconAtlasJSON,
|
|
52
|
+
onBack,
|
|
53
|
+
}) => {
|
|
54
|
+
const isMobile = isMobileOrTablet();
|
|
55
|
+
const [lootSearchQuery, setLootSearchQuery] = useState('');
|
|
56
|
+
const [currentLootPage, setCurrentLootPage] = useState(1);
|
|
57
|
+
|
|
58
|
+
const formatText = (text: string | RangeTypes | MovementSpeed): string => {
|
|
59
|
+
if (typeof text === 'number') {
|
|
60
|
+
return text.toString();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return text
|
|
64
|
+
.toString()
|
|
65
|
+
.replace(/([A-Z])/g, ' $1')
|
|
66
|
+
.trim()
|
|
67
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
68
|
+
.replace(/\s+/g, ' ')
|
|
69
|
+
.replace(/^\w/, c => c.toUpperCase());
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const formatRarity = (rarity: number): string => {
|
|
73
|
+
switch (rarity) {
|
|
74
|
+
case 0.5:
|
|
75
|
+
return 'Very Rare';
|
|
76
|
+
case 1:
|
|
77
|
+
return 'Rare';
|
|
78
|
+
case 10:
|
|
79
|
+
return 'Uncommon';
|
|
80
|
+
case 15:
|
|
81
|
+
return 'Semi Common';
|
|
82
|
+
case 20:
|
|
83
|
+
return 'Common';
|
|
84
|
+
case 35:
|
|
85
|
+
return 'Very Common';
|
|
86
|
+
default:
|
|
87
|
+
return 'Unknown';
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const filteredLoots =
|
|
92
|
+
npc.loots?.filter(loot =>
|
|
93
|
+
formatItemName(loot.itemBlueprintKey)
|
|
94
|
+
.toLowerCase()
|
|
95
|
+
.includes(lootSearchQuery.toLowerCase())
|
|
96
|
+
) || [];
|
|
97
|
+
|
|
98
|
+
const totalLootPages = Math.ceil(filteredLoots.length / ITEMS_PER_PAGE);
|
|
99
|
+
const paginatedLoots = filteredLoots.slice(
|
|
100
|
+
(currentLootPage - 1) * ITEMS_PER_PAGE,
|
|
101
|
+
currentLootPage * ITEMS_PER_PAGE
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<BaseInformationDetails
|
|
106
|
+
name={npc.name}
|
|
107
|
+
spriteKey={npc.key}
|
|
108
|
+
atlasJSON={entitiesAtlasJSON}
|
|
109
|
+
atlasIMG={entitiesAtlasIMG}
|
|
110
|
+
onBack={onBack}
|
|
111
|
+
>
|
|
112
|
+
<InfoSection>
|
|
113
|
+
<InfoItem>
|
|
114
|
+
<Label>Type:</Label>
|
|
115
|
+
<Value>{formatText(npc.subType)}</Value>
|
|
116
|
+
</InfoItem>
|
|
117
|
+
<InfoItem>
|
|
118
|
+
<Label>Alignment:</Label>
|
|
119
|
+
<Value>{formatText(npc.alignment)}</Value>
|
|
120
|
+
</InfoItem>
|
|
121
|
+
<InfoItem>
|
|
122
|
+
<Label>Attack Type:</Label>
|
|
123
|
+
<Value>{formatText(npc.attackType)}</Value>
|
|
124
|
+
</InfoItem>
|
|
125
|
+
<InfoItem>
|
|
126
|
+
<Label>Range:</Label>
|
|
127
|
+
<Value>{formatText(npc.maxRangeAttack)}</Value>
|
|
128
|
+
</InfoItem>
|
|
129
|
+
<InfoItem>
|
|
130
|
+
<Label>Speed:</Label>
|
|
131
|
+
<Value>{formatText(npc.speed)}</Value>
|
|
132
|
+
</InfoItem>
|
|
133
|
+
</InfoSection>
|
|
134
|
+
|
|
135
|
+
<StyledCollapsible title="Stats" defaultOpen={!isMobile}>
|
|
136
|
+
<StatGrid>
|
|
137
|
+
<StatItem>HP: {npc.baseHealth}</StatItem>
|
|
138
|
+
<StatItem>Level: {npc.skills.level}</StatItem>
|
|
139
|
+
{npc.skills.strength?.level && (
|
|
140
|
+
<StatItem>Strength: {npc.skills.strength.level}</StatItem>
|
|
141
|
+
)}
|
|
142
|
+
{npc.skills.dexterity?.level && (
|
|
143
|
+
<StatItem>Dexterity: {npc.skills.dexterity.level}</StatItem>
|
|
144
|
+
)}
|
|
145
|
+
{npc.skills.resistance?.level && (
|
|
146
|
+
<StatItem>Resistance: {npc.skills.resistance.level}</StatItem>
|
|
147
|
+
)}
|
|
148
|
+
</StatGrid>
|
|
149
|
+
</StyledCollapsible>
|
|
150
|
+
|
|
151
|
+
{npc.loots && npc.loots.length > 0 && (
|
|
152
|
+
<StyledCollapsible title="Loot" defaultOpen={!isMobile}>
|
|
153
|
+
<LootSearchContainer>
|
|
154
|
+
<StyledSearchBar
|
|
155
|
+
value={lootSearchQuery}
|
|
156
|
+
onChange={setLootSearchQuery}
|
|
157
|
+
placeholder="Search loot..."
|
|
158
|
+
/>
|
|
159
|
+
</LootSearchContainer>
|
|
160
|
+
<LootGrid>
|
|
161
|
+
{paginatedLoots.map((loot, index) => (
|
|
162
|
+
<LootItem key={index}>
|
|
163
|
+
<SpriteFromAtlas
|
|
164
|
+
atlasJSON={itemsAtlasJSON}
|
|
165
|
+
atlasIMG={itemsAtlasIMG}
|
|
166
|
+
spriteKey={loot.itemBlueprintKey}
|
|
167
|
+
width={24}
|
|
168
|
+
height={24}
|
|
169
|
+
imgScale={1}
|
|
170
|
+
/>
|
|
171
|
+
<LootDetails>
|
|
172
|
+
<LootName>{formatItemName(loot.itemBlueprintKey)}</LootName>
|
|
173
|
+
<LootInfo>
|
|
174
|
+
<LootChance>{formatRarity(loot.chance)}</LootChance>
|
|
175
|
+
{loot.quantityRange && (
|
|
176
|
+
<LootQuantity>
|
|
177
|
+
x{loot.quantityRange[0]}-{loot.quantityRange[1]}
|
|
178
|
+
</LootQuantity>
|
|
179
|
+
)}
|
|
180
|
+
</LootInfo>
|
|
181
|
+
</LootDetails>
|
|
182
|
+
</LootItem>
|
|
183
|
+
))}
|
|
184
|
+
</LootGrid>
|
|
185
|
+
{filteredLoots.length > ITEMS_PER_PAGE && (
|
|
186
|
+
<PaginationContainer>
|
|
187
|
+
<StyledPagination
|
|
188
|
+
currentPage={currentLootPage}
|
|
189
|
+
totalPages={totalLootPages}
|
|
190
|
+
onPageChange={setCurrentLootPage}
|
|
191
|
+
/>
|
|
192
|
+
</PaginationContainer>
|
|
193
|
+
)}
|
|
194
|
+
</StyledCollapsible>
|
|
195
|
+
)}
|
|
196
|
+
|
|
197
|
+
{npc.entityEffects && npc.entityEffects.length > 0 && (
|
|
198
|
+
<StyledCollapsible title="Effects" defaultOpen={!isMobile}>
|
|
199
|
+
<EffectsList>
|
|
200
|
+
{npc.entityEffects.map((effect, index) => (
|
|
201
|
+
<EffectItem key={index}>{formatText(effect)}</EffectItem>
|
|
202
|
+
))}
|
|
203
|
+
</EffectsList>
|
|
204
|
+
</StyledCollapsible>
|
|
205
|
+
)}
|
|
206
|
+
|
|
207
|
+
{npc.areaSpells && npc.areaSpells.length > 0 && (
|
|
208
|
+
<StyledCollapsible title="Spells" defaultOpen={!isMobile}>
|
|
209
|
+
<SpellsList>
|
|
210
|
+
{npc.areaSpells.map((spell, index) => (
|
|
211
|
+
<SpellItem key={index}>
|
|
212
|
+
<SpellIconContainer>
|
|
213
|
+
<SpriteFromAtlas
|
|
214
|
+
atlasJSON={iconAtlasJSON}
|
|
215
|
+
atlasIMG={iconAtlasIMG}
|
|
216
|
+
spriteKey={spell.texturePath || spell.spellKey}
|
|
217
|
+
width={24}
|
|
218
|
+
height={24}
|
|
219
|
+
imgScale={1}
|
|
220
|
+
/>
|
|
221
|
+
</SpellIconContainer>
|
|
222
|
+
<SpellContent>
|
|
223
|
+
<SpellName>{formatText(spell.spellKey)}</SpellName>
|
|
224
|
+
<SpellDetails>
|
|
225
|
+
Power: <SpellValue>{formatText(spell.power)}</SpellValue>
|
|
226
|
+
<Separator>•</Separator>
|
|
227
|
+
Chance: <SpellValue>{spell.probability}%</SpellValue>
|
|
228
|
+
</SpellDetails>
|
|
229
|
+
</SpellContent>
|
|
230
|
+
</SpellItem>
|
|
231
|
+
))}
|
|
232
|
+
</SpellsList>
|
|
233
|
+
</StyledCollapsible>
|
|
234
|
+
)}
|
|
235
|
+
</BaseInformationDetails>
|
|
236
|
+
);
|
|
237
|
+
};
|
|
244
238
|
|
|
245
239
|
const InfoSection = styled.div`
|
|
246
240
|
display: grid;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IInformationCenterNPC,
|
|
3
|
+
MovementSpeed,
|
|
4
|
+
RangeTypes,
|
|
5
|
+
} from '@rpg-engine/shared';
|
|
2
6
|
import React from 'react';
|
|
3
7
|
import styled from 'styled-components';
|
|
4
8
|
import { uiColors } from '../../../../constants/uiColors';
|
|
@@ -10,10 +14,7 @@ import BaseTooltip, {
|
|
|
10
14
|
TooltipTitle,
|
|
11
15
|
} from '../../../shared/BaseTooltip';
|
|
12
16
|
import { SpriteFromAtlas } from '../../../shared/SpriteFromAtlas';
|
|
13
|
-
import {
|
|
14
|
-
IInformationCenterNPC,
|
|
15
|
-
MovementSpeed,
|
|
16
|
-
} from '../../InformationCenterTypes';
|
|
17
|
+
import { formatItemName } from './InformationCenterNPCDetails';
|
|
17
18
|
|
|
18
19
|
interface INPCTooltipProps {
|
|
19
20
|
npc: IInformationCenterNPC;
|
|
@@ -191,7 +192,7 @@ export const InformationCenterNPCTooltip: React.FC<INPCTooltipProps> = ({
|
|
|
191
192
|
spriteKey={loot.itemBlueprintKey}
|
|
192
193
|
imgScale={1}
|
|
193
194
|
/>
|
|
194
|
-
<LootName>{
|
|
195
|
+
<LootName>{formatItemName(loot.itemBlueprintKey)}</LootName>
|
|
195
196
|
<LootChance>{formatRarity(loot.chance)}</LootChance>
|
|
196
197
|
</LootItem>
|
|
197
198
|
))}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { IFaqItem } from '@rpg-engine/shared';
|
|
1
2
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
3
|
import styled from 'styled-components';
|
|
3
4
|
import { Collapsible } from '../../../shared/Collapsible/Collapsible';
|
|
4
5
|
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
|
|
5
6
|
import { SearchHeader } from '../../../shared/SearchHeader/SearchHeader';
|
|
6
|
-
import { IFaqItem } from '../../InformationCenter';
|
|
7
7
|
|
|
8
8
|
interface IFaqSectionProps {
|
|
9
9
|
faqItems: IFaqItem[];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IInformationCenterItem,
|
|
3
|
+
IInformationCenterNPC,
|
|
4
|
+
isMobileOrTablet,
|
|
5
|
+
} from '@rpg-engine/shared';
|
|
2
6
|
import React from 'react';
|
|
3
7
|
import styled from 'styled-components';
|
|
4
8
|
import { uiColors } from '../../../../constants/uiColors';
|
|
5
9
|
import { Collapsible } from '../../../shared/Collapsible/Collapsible';
|
|
6
|
-
import {
|
|
7
|
-
IInformationCenterItem,
|
|
8
|
-
IInformationCenterNPC,
|
|
9
|
-
} from '../../InformationCenterTypes';
|
|
10
10
|
import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
|
|
11
11
|
|
|
12
12
|
interface IInformationCenterItemDetailsProps {
|
|
@@ -130,7 +130,9 @@ export const InformationCenterItemDetails: React.FC<IInformationCenterItemDetail
|
|
|
130
130
|
<BuffsList>
|
|
131
131
|
{item.equippedBuff.map((buff, index) => (
|
|
132
132
|
<BuffItem key={index}>
|
|
133
|
-
<BuffName>
|
|
133
|
+
<BuffName>
|
|
134
|
+
{buff.trait.replace(/^\w/, c => c.toUpperCase())}
|
|
135
|
+
</BuffName>
|
|
134
136
|
<BuffValue>+{buff.buffPercentage}%</BuffValue>
|
|
135
137
|
</BuffItem>
|
|
136
138
|
))}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IInformationCenterItem } from '@rpg-engine/shared';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import styled from 'styled-components';
|
|
3
4
|
import { uiColors } from '../../../../constants/uiColors';
|
|
@@ -8,7 +9,6 @@ import BaseTooltip, {
|
|
|
8
9
|
StatsContainer,
|
|
9
10
|
TooltipTitle,
|
|
10
11
|
} from '../../../shared/BaseTooltip';
|
|
11
|
-
import { IInformationCenterItem } from '../../InformationCenterTypes';
|
|
12
12
|
|
|
13
13
|
interface IItemTooltipProps {
|
|
14
14
|
item: IInformationCenterItem;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IInformationCenterItem,
|
|
3
|
+
IInformationCenterNPC,
|
|
4
|
+
ItemType,
|
|
5
|
+
} from '@rpg-engine/shared';
|
|
2
6
|
import React, { useState } from 'react';
|
|
3
7
|
import styled from 'styled-components';
|
|
4
8
|
import { IOptionsProps } from '../../../Dropdown';
|
|
5
9
|
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
|
|
6
10
|
import { InformationCenterCell } from '../../InformationCenterCell';
|
|
7
|
-
import {
|
|
8
|
-
IInformationCenterItem,
|
|
9
|
-
IInformationCenterNPC,
|
|
10
|
-
} from '../../InformationCenterTypes';
|
|
11
11
|
import { InformationCenterItemDetails } from './InformationCenterItemDetails';
|
|
12
12
|
import { InformationCenterItemTooltip } from './InformationCenterItemTooltip';
|
|
13
13
|
|
|
14
|
-
const TOOLTIP_OFFSET =
|
|
14
|
+
const TOOLTIP_OFFSET = 200;
|
|
15
15
|
|
|
16
16
|
interface IItemsSectionProps {
|
|
17
17
|
items: IInformationCenterItem[];
|
|
@@ -22,6 +22,23 @@ interface IItemsSectionProps {
|
|
|
22
22
|
tabId: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export const formatItemType = (type: string): string => {
|
|
26
|
+
const words = type.split(/(?=[A-Z])/);
|
|
27
|
+
|
|
28
|
+
if (words.length === 1) {
|
|
29
|
+
return words[0];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return words
|
|
33
|
+
.map((word, index) => {
|
|
34
|
+
if (index === 0) {
|
|
35
|
+
return word.charAt(0) + '.';
|
|
36
|
+
}
|
|
37
|
+
return word;
|
|
38
|
+
})
|
|
39
|
+
.join(' ');
|
|
40
|
+
};
|
|
41
|
+
|
|
25
42
|
export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
26
43
|
items,
|
|
27
44
|
bestiaryItems,
|
|
@@ -45,9 +62,11 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
45
62
|
|
|
46
63
|
const itemCategoryOptions: IOptionsProps[] = [
|
|
47
64
|
{ id: 0, value: 'all', option: 'All Items' },
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
...Object.values(ItemType).map((type, index) => ({
|
|
66
|
+
id: index + 1,
|
|
67
|
+
value: type,
|
|
68
|
+
option: formatItemType(type),
|
|
69
|
+
})),
|
|
51
70
|
];
|
|
52
71
|
|
|
53
72
|
const filteredItems = items.filter(
|
|
@@ -108,6 +127,13 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
108
127
|
setHoveredItem(null);
|
|
109
128
|
};
|
|
110
129
|
|
|
130
|
+
const handleSearchChange = (newQuery: string) => {
|
|
131
|
+
setSearchQuery(newQuery);
|
|
132
|
+
if (newQuery && selectedItemCategory !== 'all') {
|
|
133
|
+
setSelectedItemCategory('all');
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
111
137
|
const renderItem = (item: IInformationCenterItem) => (
|
|
112
138
|
<InformationCenterCell
|
|
113
139
|
key={item.key}
|
|
@@ -136,7 +162,7 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
|
|
|
136
162
|
}}
|
|
137
163
|
searchOptions={{
|
|
138
164
|
value: searchQuery,
|
|
139
|
-
onChange:
|
|
165
|
+
onChange: handleSearchChange,
|
|
140
166
|
placeholder: 'Search items...',
|
|
141
167
|
}}
|
|
142
168
|
dependencies={[selectedItemCategory]}
|