@rpg-engine/long-bow 0.8.20 → 0.8.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.
Files changed (33) hide show
  1. package/dist/components/InformationCenter/InformationCenter.d.ts +5 -15
  2. package/dist/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.d.ts +3 -1
  3. package/dist/components/InformationCenter/sections/bestiary/InformationCenterNPCDetails.d.ts +4 -1
  4. package/dist/components/InformationCenter/sections/bestiary/InformationCenterNPCTooltip.d.ts +1 -1
  5. package/dist/components/InformationCenter/sections/faq/InformationCenterFaqSection.d.ts +1 -1
  6. package/dist/components/InformationCenter/sections/items/InformationCenterItemDetails.d.ts +1 -1
  7. package/dist/components/InformationCenter/sections/items/InformationCenterItemTooltip.d.ts +1 -1
  8. package/dist/components/InformationCenter/sections/items/InformationCenterItemsSection.d.ts +2 -1
  9. package/dist/components/InformationCenter/sections/tutorials/InformationCenterTutorialsSection.d.ts +1 -1
  10. package/dist/long-bow.cjs.development.js +793 -660
  11. package/dist/long-bow.cjs.development.js.map +1 -1
  12. package/dist/long-bow.cjs.production.min.js +1 -1
  13. package/dist/long-bow.cjs.production.min.js.map +1 -1
  14. package/dist/long-bow.esm.js +794 -661
  15. package/dist/long-bow.esm.js.map +1 -1
  16. package/dist/mocks/informationCenter.mocks.d.ts +1 -2
  17. package/package.json +2 -2
  18. package/src/components/CraftBook/CraftBook.tsx +1 -1
  19. package/src/components/Dropdown.tsx +25 -3
  20. package/src/components/InformationCenter/InformationCenter.tsx +11 -18
  21. package/src/components/InformationCenter/sections/bestiary/InformationCenterBestiarySection.tsx +58 -7
  22. package/src/components/InformationCenter/sections/bestiary/InformationCenterNPCDetails.tsx +63 -15
  23. package/src/components/InformationCenter/sections/bestiary/InformationCenterNPCTooltip.tsx +7 -6
  24. package/src/components/InformationCenter/sections/faq/InformationCenterFaqSection.tsx +1 -1
  25. package/src/components/InformationCenter/sections/items/InformationCenterItemDetails.tsx +8 -6
  26. package/src/components/InformationCenter/sections/items/InformationCenterItemTooltip.tsx +1 -1
  27. package/src/components/InformationCenter/sections/items/InformationCenterItemsSection.tsx +36 -10
  28. package/src/components/InformationCenter/sections/tutorials/InformationCenterTutorialsSection.tsx +133 -34
  29. package/src/components/shared/PaginatedContent/PaginatedContent.tsx +1 -1
  30. package/src/mocks/informationCenter.mocks.ts +175 -55
  31. package/src/stories/UI/info/InformationCenter.stories.tsx +6 -1
  32. package/dist/components/InformationCenter/InformationCenterTypes.d.ts +0 -79
  33. package/src/components/InformationCenter/InformationCenterTypes.ts +0 -87
@@ -1,5 +1,4 @@
1
- import { IFaqItem, IVideoGuide } from '../components/InformationCenter/InformationCenter';
2
- import { IInformationCenterItem, IInformationCenterNPC } from '../components/InformationCenter/InformationCenterTypes';
1
+ import { IFaqItem, IInformationCenterItem, IInformationCenterNPC, IVideoGuide } from '@rpg-engine/shared';
3
2
  export declare const mockBestiaryItems: IInformationCenterNPC[];
4
3
  export declare const mockItems: IInformationCenterItem[];
5
4
  export declare const mockFaqItems: IFaqItem[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.20",
3
+ "version": "0.8.22",
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.9.96",
87
+ "@rpg-engine/shared": "^0.9.101",
88
88
  "dayjs": "^1.11.2",
89
89
  "font-awesome": "^4.7.0",
90
90
  "fs-extra": "^10.1.0",
@@ -368,7 +368,7 @@ const ContentContainer = styled.div`
368
368
  padding-bottom: 0;
369
369
  width: 100%;
370
370
  position: relative;
371
- min-height: 250px;
371
+ min-height: 300px;
372
372
  overflow: hidden;
373
373
  `;
374
374
 
@@ -15,6 +15,10 @@ export interface IDropdownProps {
15
15
  opensUp?: boolean; // Add a new prop to control the dropdown direction
16
16
  }
17
17
 
18
+ const ITEM_HEIGHT = 35;
19
+ const MAX_ITEMS_VISIBLE = 10;
20
+ const MAX_HEIGHT = MAX_ITEMS_VISIBLE * ITEM_HEIGHT;
21
+
18
22
  export const Dropdown: React.FC<IDropdownProps> = ({
19
23
  options,
20
24
  width,
@@ -65,6 +69,7 @@ export const Dropdown: React.FC<IDropdownProps> = ({
65
69
  className="rpgui-dropdown-imp"
66
70
  opened={opened}
67
71
  opensUp={opensUp}
72
+ optionsCount={options.length}
68
73
  >
69
74
  {options.map(option => {
70
75
  return (
@@ -88,11 +93,16 @@ export const Dropdown: React.FC<IDropdownProps> = ({
88
93
  const Container = styled.div<{ width: string | undefined }>`
89
94
  position: relative;
90
95
  width: ${props => props.width || '100%'};
96
+ max-height: ${MAX_HEIGHT}px;
91
97
  `;
92
98
 
93
99
  const DropdownSelect = styled.p`
94
100
  width: 100%;
95
101
  box-sizing: border-box;
102
+ white-space: nowrap;
103
+ overflow: hidden;
104
+ text-overflow: ellipsis;
105
+ max-height: ${ITEM_HEIGHT}px;
96
106
 
97
107
  label {
98
108
  display: inline-block;
@@ -103,10 +113,14 @@ const DropdownSelect = styled.p`
103
113
  const DropdownOptions = styled.ul<{
104
114
  opened: boolean;
105
115
  opensUp: boolean;
116
+ optionsCount: number;
106
117
  }>`
107
118
  position: absolute;
108
119
  width: 100%;
109
- max-height: 300px;
120
+ max-height: ${props =>
121
+ props.opened
122
+ ? `${Math.min(props.optionsCount * ITEM_HEIGHT, MAX_HEIGHT)}px`
123
+ : '0'};
110
124
  overflow-y: auto;
111
125
  display: ${props => (props.opened ? 'block' : 'none')};
112
126
  box-sizing: border-box;
@@ -114,7 +128,15 @@ const DropdownOptions = styled.ul<{
114
128
  top: ${props => (props.opensUp ? 'auto' : '100%')};
115
129
  margin: 0;
116
130
  padding: 0;
117
- @media (max-width: 768px) {
118
- padding: 8px 0;
131
+
132
+ li {
133
+ white-space: nowrap;
134
+ overflow: hidden;
135
+ text-overflow: ellipsis;
136
+ padding: 8px 12px;
137
+ min-height: ${ITEM_HEIGHT}px;
138
+ max-height: ${ITEM_HEIGHT}px;
139
+ box-sizing: border-box;
140
+ line-height: 1.2;
119
141
  }
120
142
  `;
@@ -1,37 +1,26 @@
1
1
  import React, { useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
- import { InternalTabs } from '../InternalTabs/InternalTabs';
5
4
  import {
5
+ IFaqItem,
6
6
  IInformationCenterItem,
7
7
  IInformationCenterNPC,
8
- } from './InformationCenterTypes';
8
+ IVideoGuide,
9
+ } from '@rpg-engine/shared';
10
+ import { InternalTabs } from '../InternalTabs/InternalTabs';
9
11
  import { InformationCenterBestiarySection } from './sections/bestiary/InformationCenterBestiarySection';
10
12
  import { InformationCenterFAQSection } from './sections/faq/InformationCenterFaqSection';
11
13
  import { InformationCenterItemDetails } from './sections/items/InformationCenterItemDetails';
12
14
  import { InformationCenterItemsSection } from './sections/items/InformationCenterItemsSection';
13
15
  import { InformationCenterTutorialsSection } from './sections/tutorials/InformationCenterTutorialsSection';
14
16
 
15
- export interface IFaqItem {
16
- id: string;
17
- question: string;
18
- answer: string;
19
- }
20
-
21
- export interface IVideoGuide {
22
- id: string;
23
- title: string;
24
- description: string;
25
- thumbnailUrl: string;
26
- videoUrl: string;
27
- category: 'Combat' | 'Crafting' | 'Exploration' | 'General';
28
- }
29
-
30
- export interface IInformationCenterProps {
17
+ interface IInformationCenterProps {
31
18
  itemsAtlasJSON: Record<string, any>;
32
19
  itemsAtlasIMG: string;
33
20
  entitiesAtlasJSON: Record<string, any>;
34
21
  entitiesAtlasIMG: string;
22
+ iconsAtlasJSON: any;
23
+ iconsAtlasIMG: any;
35
24
  faqItems?: IFaqItem[];
36
25
  bestiaryItems?: IInformationCenterNPC[];
37
26
  videoGuides?: IVideoGuide[];
@@ -46,6 +35,8 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
46
35
  itemsAtlasIMG,
47
36
  entitiesAtlasJSON,
48
37
  entitiesAtlasIMG,
38
+ iconsAtlasIMG,
39
+ iconsAtlasJSON,
49
40
  faqItems = [],
50
41
  bestiaryItems = [],
51
42
  videoGuides = [],
@@ -77,6 +68,8 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
77
68
  bestiaryItems={bestiaryItems}
78
69
  itemsAtlasJSON={itemsAtlasJSON}
79
70
  itemsAtlasIMG={itemsAtlasIMG}
71
+ iconsAtlasIMG={iconsAtlasIMG}
72
+ iconsAtlasJSON={iconsAtlasJSON}
80
73
  entitiesAtlasJSON={entitiesAtlasJSON}
81
74
  entitiesAtlasIMG={entitiesAtlasIMG}
82
75
  initialSearchQuery={initialSearchQuery}
@@ -1,18 +1,21 @@
1
- import React, { useState } from 'react';
1
+ import { IInformationCenterNPC, NPCAlignment } from '@rpg-engine/shared';
2
+ import React, { useMemo, useState } from 'react';
2
3
  import styled from 'styled-components';
4
+ import { IOptionsProps } from '../../../Dropdown';
3
5
  import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
4
6
  import { Portal } from '../../../shared/Portal/Portal';
5
7
  import { InformationCenterCell } from '../../InformationCenterCell';
6
- import { IInformationCenterNPC } from '../../InformationCenterTypes';
8
+ import { formatItemType } from '../items/InformationCenterItemsSection';
7
9
  import { InformationCenterNPCDetails } from './InformationCenterNPCDetails';
8
10
  import { InformationCenterNPCTooltip } from './InformationCenterNPCTooltip';
9
-
10
11
  interface IBestiarySectionProps {
11
12
  bestiaryItems: IInformationCenterNPC[];
12
13
  itemsAtlasJSON: Record<string, any>;
13
14
  itemsAtlasIMG: string;
14
15
  entitiesAtlasJSON: Record<string, any>;
15
16
  entitiesAtlasIMG: string;
17
+ iconsAtlasIMG: any;
18
+ iconsAtlasJSON: any;
16
19
  initialSearchQuery: string;
17
20
  tabId: string;
18
21
  }
@@ -21,6 +24,8 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
21
24
  bestiaryItems,
22
25
  itemsAtlasJSON,
23
26
  itemsAtlasIMG,
27
+ iconsAtlasIMG,
28
+ iconsAtlasJSON,
24
29
  entitiesAtlasJSON,
25
30
  entitiesAtlasIMG,
26
31
  initialSearchQuery,
@@ -87,6 +92,20 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
87
92
  setTooltipData(null);
88
93
  };
89
94
 
95
+ const [selectedBestiaryCategory, setSelectedBestiaryCategory] = useState<
96
+ string
97
+ >('all');
98
+
99
+ const bestiaryCategoryOptions: IOptionsProps[] = [
100
+ { id: 0, value: 'all', option: 'All Monsters' },
101
+ { id: 1, value: 'bosses', option: 'Bosses' },
102
+ ...Object.entries(NPCAlignment).map(([, value], index) => ({
103
+ id: index + 1,
104
+ value,
105
+ option: formatItemType(value),
106
+ })),
107
+ ];
108
+
90
109
  const renderItem = (item: IInformationCenterNPC) => (
91
110
  <InformationCenterCell
92
111
  key={item.id}
@@ -102,9 +121,33 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
102
121
  />
103
122
  );
104
123
 
105
- const filteredItems = bestiaryItems.filter(item =>
106
- item.name.toLowerCase().includes(searchQuery.toLowerCase())
107
- );
124
+ const filteredItems = useMemo(() => {
125
+ return bestiaryItems.filter(item => {
126
+ const matchesSearch = item.name
127
+ .toLowerCase()
128
+ .includes(searchQuery.toLowerCase());
129
+
130
+ let matchesCategory = true;
131
+
132
+ if (selectedBestiaryCategory === 'bosses') {
133
+ matchesCategory = item.isBoss === true;
134
+ } else if (selectedBestiaryCategory === NPCAlignment.Hostile) {
135
+ matchesCategory =
136
+ item.alignment === NPCAlignment.Hostile && !item.isBoss;
137
+ } else if (selectedBestiaryCategory !== 'all') {
138
+ matchesCategory = item.alignment === selectedBestiaryCategory;
139
+ }
140
+
141
+ return matchesSearch && matchesCategory;
142
+ });
143
+ }, [bestiaryItems, searchQuery, selectedBestiaryCategory]);
144
+
145
+ const handleSearchChange = (newQuery: string) => {
146
+ setSearchQuery(newQuery);
147
+ if (newQuery && selectedBestiaryCategory !== 'all') {
148
+ setSelectedBestiaryCategory('all');
149
+ }
150
+ };
108
151
 
109
152
  return (
110
153
  <>
@@ -114,11 +157,17 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
114
157
  emptyMessage="No monsters found"
115
158
  tabId={tabId}
116
159
  layout="grid"
160
+ filterOptions={{
161
+ options: bestiaryCategoryOptions,
162
+ selectedOption: selectedBestiaryCategory,
163
+ onOptionChange: setSelectedBestiaryCategory,
164
+ }}
117
165
  searchOptions={{
118
166
  value: searchQuery,
119
- onChange: setSearchQuery,
167
+ onChange: handleSearchChange,
120
168
  placeholder: 'Search monsters...',
121
169
  }}
170
+ dependencies={[selectedBestiaryCategory]}
122
171
  itemHeight="180px"
123
172
  />
124
173
  {tooltipData && (
@@ -143,6 +192,8 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
143
192
  npc={selectedMonster}
144
193
  itemsAtlasJSON={itemsAtlasJSON}
145
194
  itemsAtlasIMG={itemsAtlasIMG}
195
+ iconAtlasIMG={iconsAtlasIMG}
196
+ iconAtlasJSON={iconsAtlasJSON}
146
197
  entitiesAtlasJSON={entitiesAtlasJSON}
147
198
  entitiesAtlasIMG={entitiesAtlasIMG}
148
199
  onBack={() => setSelectedMonster(null)}
@@ -1,4 +1,9 @@
1
- import { isMobileOrTablet, RangeTypes } from '@rpg-engine/shared';
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
- import {
10
- IInformationCenterNPC,
11
- MovementSpeed,
12
- } from '../../InformationCenterTypes';
14
+
13
15
  import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
14
16
 
15
17
  interface INPCDetailsProps {
@@ -18,17 +20,35 @@ interface INPCDetailsProps {
18
20
  itemsAtlasIMG: string;
19
21
  entitiesAtlasJSON: Record<string, any>;
20
22
  entitiesAtlasIMG: string;
23
+ iconAtlasIMG?: any;
24
+ iconAtlasJSON?: any;
21
25
  onBack: () => void;
22
26
  }
23
27
 
24
28
  const ITEMS_PER_PAGE = 5;
25
29
 
30
+ export const formatItemName = (itemPath: string): string => {
31
+ const cleanText =
32
+ itemPath
33
+ .split('/')
34
+ .pop()
35
+ ?.split('.')
36
+ .shift() || '';
37
+
38
+ return cleanText
39
+ .split('-')
40
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
41
+ .join(' ');
42
+ };
43
+
26
44
  export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
27
45
  npc,
28
46
  itemsAtlasJSON,
29
47
  itemsAtlasIMG,
30
48
  entitiesAtlasJSON,
31
49
  entitiesAtlasIMG,
50
+ iconAtlasIMG,
51
+ iconAtlasJSON,
32
52
  onBack,
33
53
  }) => {
34
54
  const isMobile = isMobileOrTablet();
@@ -39,12 +59,14 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
39
59
  if (typeof text === 'number') {
40
60
  return text.toString();
41
61
  }
62
+
42
63
  return text
43
64
  .toString()
44
65
  .replace(/([A-Z])/g, ' $1')
45
66
  .trim()
46
67
  .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
47
- .replace(/\s+/g, ' ');
68
+ .replace(/\s+/g, ' ')
69
+ .replace(/^\w/, c => c.toUpperCase());
48
70
  };
49
71
 
50
72
  const formatRarity = (rarity: number): string => {
@@ -68,7 +90,7 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
68
90
 
69
91
  const filteredLoots =
70
92
  npc.loots?.filter(loot =>
71
- formatText(loot.itemBlueprintKey)
93
+ formatItemName(loot.itemBlueprintKey)
72
94
  .toLowerCase()
73
95
  .includes(lootSearchQuery.toLowerCase())
74
96
  ) || [];
@@ -147,7 +169,7 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
147
169
  imgScale={1}
148
170
  />
149
171
  <LootDetails>
150
- <LootName>{formatText(loot.itemBlueprintKey)}</LootName>
172
+ <LootName>{formatItemName(loot.itemBlueprintKey)}</LootName>
151
173
  <LootInfo>
152
174
  <LootChance>{formatRarity(loot.chance)}</LootChance>
153
175
  {loot.quantityRange && (
@@ -187,12 +209,24 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
187
209
  <SpellsList>
188
210
  {npc.areaSpells.map((spell, index) => (
189
211
  <SpellItem key={index}>
190
- <SpellName>{formatText(spell.spellKey)}</SpellName>
191
- <SpellDetails>
192
- Power: <SpellValue>{formatText(spell.power)}</SpellValue>
193
- <Separator>•</Separator>
194
- Chance: <SpellValue>{spell.probability}%</SpellValue>
195
- </SpellDetails>
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>
196
230
  </SpellItem>
197
231
  ))}
198
232
  </SpellsList>
@@ -271,13 +305,27 @@ const SpellsList = styled.div`
271
305
  padding: 12px;
272
306
  `;
273
307
 
274
- const SpellItem = styled.div`
308
+ const SpellIconContainer = styled.div`
309
+ display: flex;
310
+ padding-right: 30px;
311
+ padding-bottom: 30px;
312
+ `;
313
+
314
+ const SpellContent = styled.div`
275
315
  display: flex;
276
316
  flex-direction: column;
277
317
  gap: 4px;
318
+ flex: 1;
319
+ `;
320
+
321
+ const SpellItem = styled.div`
322
+ display: flex;
323
+ gap: 8px;
278
324
  background: rgba(255, 255, 255, 0.05);
279
325
  padding: 8px;
326
+ padding-left: 10px;
280
327
  border-radius: 4px;
328
+ align-items: center;
281
329
  `;
282
330
 
283
331
  const SpellName = styled.div`
@@ -1,4 +1,8 @@
1
- import { RangeTypes } from '@rpg-engine/shared';
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>{formatText(loot.itemBlueprintKey)}</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 { isMobileOrTablet } from '@rpg-engine/shared';
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>{buff.trait}</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 { ItemType } from '@rpg-engine/shared';
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 = 20;
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
- { id: 1, value: ItemType.Consumable, option: 'Consumables' },
49
- { id: 2, value: ItemType.Weapon, option: 'Weapons' },
50
- { id: 3, value: ItemType.Armor, option: 'Armor' },
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: setSearchQuery,
165
+ onChange: handleSearchChange,
140
166
  placeholder: 'Search items...',
141
167
  }}
142
168
  dependencies={[selectedItemCategory]}